Browse Source

Merge pull request #4242 from cakephp/3.0-table-save-id

Fix entity saving when '' is used as a primary key value.
José Lorenzo Rodríguez 11 years ago
parent
commit
2edcc0b992
3 changed files with 29 additions and 4 deletions
  1. 4 0
      src/ORM/Marshaller.php
  2. 4 4
      src/ORM/Table.php
  3. 21 0
      tests/TestCase/ORM/MarshallerTest.php

+ 4 - 0
src/ORM/Marshaller.php

@@ -106,12 +106,16 @@ class Marshaller {
 			$data = $data[$tableName];
 		}
 
+		$primaryKey = $schema->primaryKey();
 		$properties = [];
 		foreach ($data as $key => $value) {
 			$columnType = $schema->columnType($key);
 			if (isset($propertyMap[$key])) {
 				$assoc = $propertyMap[$key]['association'];
 				$value = $this->_marshalAssociation($assoc, $value, $propertyMap[$key]);
+			} elseif ($value === '' && in_array($key, $primaryKey, true)) {
+				// Skip marshalling '' for pk fields.
+				continue;
 			} elseif ($columnType) {
 				$converter = Type::build($columnType);
 				$value = $converter->marshal($value);

+ 4 - 4
src/ORM/Table.php

@@ -1150,11 +1150,11 @@ class Table implements RepositoryInterface, EventListener {
 
 		if ($primary && $entity->isNew()) {
 			$alias = $this->alias();
-			$keys = array_keys($primary);
-			foreach ($keys as &$pk) {
-				$pk = "$alias.$pk";
+			$conditions = [];
+			foreach ($primary as $k => $v) {
+				$conditions["$alias.$k"] = $v;
 			}
-			$entity->isNew(!$this->exists(array_combine($keys, $primary)));
+			$entity->isNew(!$this->exists($conditions));
 		}
 
 		$associated = $options['associated'];

+ 21 - 0
tests/TestCase/ORM/MarshallerTest.php

@@ -115,6 +115,27 @@ class MarshallerTest extends TestCase {
 	}
 
 /**
+ * Test that marshalling an entity with '' for pk values results
+ * in no pk value being set.
+ *
+ * @return void
+ */
+	public function testOneEmptyStringPrimaryKey() {
+		$data = [
+			'id' => '',
+			'username' => 'superuser',
+			'password' => 'root',
+			'created' => new Time('2013-10-10 00:00'),
+			'updated' => new Time('2013-10-10 00:00')
+		];
+		$marshall = new Marshaller($this->articles);
+		$result = $marshall->one($data, []);
+
+		$this->assertFalse($result->dirty('id'));
+		$this->assertNull($result->id);
+	}
+
+/**
  * Test marshalling datetime/date field.
  *
  * @return void