Skip to content
Permalink
Browse files

Avoding wastful UPDATE statements for HasMany associations

This prevents the ORM from issueing an update statement to the
database if no actual changes could be found
  • Loading branch information...
lorenzo committed Jul 15, 2015
1 parent 46fbae6 commit 49466ec6724e3a4765ac397d3360326f71d7543e
Showing with 48 additions and 2 deletions.
  1. +6 −2 src/ORM/Association/HasMany.php
  2. +42 −0 tests/TestCase/ORM/TableTest.php
@@ -96,8 +96,9 @@ public function saveAssociated(EntityInterface $entity, array $options = [])
throw new InvalidArgumentException($message);
}
$foreignKey = (array)$this->foreignKey();
$properties = array_combine(
(array)$this->foreignKey(),
$foreignKey,
$entity->extract((array)$this->bindingKey())
);
$target = $this->target();
@@ -113,7 +114,10 @@ public function saveAssociated(EntityInterface $entity, array $options = [])
$targetEntity = clone $targetEntity;
}
$targetEntity->set($properties, ['guard' => false]);
if ($properties !== $targetEntity->extract($foreignKey)) {
$targetEntity->set($properties, ['guard' => false]);
}
if ($target->save($targetEntity, $options)) {
$targetEntities[$k] = $targetEntity;
continue;
@@ -4322,6 +4322,11 @@ public function testSaveWithClonedEntity()
$this->assertEquals(4, $cloned->id);
}
/**
* Tests that the _ids notation can be used for HasMany
*
* @return void
*/
public function testSaveHasManyWithIds()
{
$data = [
@@ -4340,6 +4345,43 @@ public function testSaveHasManyWithIds()
$this->assertEquals($savedUser->comments[1]->user_id, $retrievedUser->comments[1]->user_id);
}
/**
* Tests that on second save, entities for the has many relation are not marked
* as dirty unnecessarily. This helps avoid wasteful database statements and makes
* for a cleaner transaction log
*
* @return void
*/
public function testSaveHasManyNoWasteSave()
{
$data = [
'username' => 'lux',
'password' => 'passphrase',
'comments' => [
'_ids' => [1, 2]
]
];
$userTable = TableRegistry::get('Users');
$userTable->hasMany('Comments');
$savedUser = $userTable->save($userTable->newEntity($data, ['associated' => ['Comments']]));
$counter = 0;
$userTable->Comments
->eventManager()
->on('Model.afterSave', function ($event, $entity) use (&$counter) {
if ($entity->dirty()) {
$counter++;
}
});
$savedUser->comments[] = $userTable->Comments->get(5);
$this->assertCount(3, $savedUser->comments);
$savedUser->dirty('comments', true);
$userTable->save($savedUser);
$this->assertEquals(1, $counter);
}
/**
* Tests that after saving then entity contains the right primary
* key casted to the right type

0 comments on commit 49466ec

Please sign in to comment.
You can’t perform that action at this time.