PrePersist event doesn't fire on subsequent persist #5625

Closed
opened 2026-01-22 15:13:07 +01:00 by admin · 3 comments
Owner

Originally created by @josefsabl on GitHub (Aug 1, 2017).

Originally assigned to: @alcaeus on GitHub.

I am not sure if this is a bug or a limitation or mistunderstood feature. It just works in a different way than I expected.

Let's assume I want to validate field of a document and set isInvalid field to TRUE if certain criteria is not met.

/**
 * @ODM\Document
 * @ODM\HasLifecycleCallbacks
 */
class Foo {
	/** @ODM\Field(type="string") */
	public $bar;

	/** @ODM\Field(type="boolean") */
	public $isInvalid = FALSE;

	/**
	 * @ODM\PrePersist
	 * @ODM\PreUpdate
	 */
	public function validate() {
		$this->isInvalid = FALSE;

		if (empty($this->bar)) {
			$this->isInvalid = TRUE;
		}
	}
}

I would assert that this test would not fail. But the second persist obviously doesn't fire PrePersist event.

$f = new Foo;

$this->getDm()->persist($f);
Assert::true($f->isInvalid);

$f->bar = 'baz';
$this->getDm()->persist($f);
Assert::false($f->isInvalid); //Fails

I am sure that by looking into code I would find out that it is designed like that intentionally. But isn't it incorrect behavior? I would understand that the second persist will not fire PrePersist as the second persist can be considered an update, but PreUpdate isn't fired either.

Would someone please clarify this or correct my assumptions and propose a solution?

Thank you.

Originally created by @josefsabl on GitHub (Aug 1, 2017). Originally assigned to: @alcaeus on GitHub. I am not sure if this is a bug or a limitation or mistunderstood feature. It just works in a different way than I expected. Let's assume I want to validate field of a document and set isInvalid field to TRUE if certain criteria is not met. ```PHP /** * @ODM\Document * @ODM\HasLifecycleCallbacks */ class Foo { /** @ODM\Field(type="string") */ public $bar; /** @ODM\Field(type="boolean") */ public $isInvalid = FALSE; /** * @ODM\PrePersist * @ODM\PreUpdate */ public function validate() { $this->isInvalid = FALSE; if (empty($this->bar)) { $this->isInvalid = TRUE; } } } ``` I would assert that this test would not fail. But the second persist obviously doesn't fire PrePersist event. ```PHP $f = new Foo; $this->getDm()->persist($f); Assert::true($f->isInvalid); $f->bar = 'baz'; $this->getDm()->persist($f); Assert::false($f->isInvalid); //Fails ``` I am sure that by looking into code I would find out that it is designed like that intentionally. But isn't it incorrect behavior? I would understand that the second persist will not fire PrePersist as the second persist can be considered an update, but PreUpdate isn't fired either. Would someone please clarify this or correct my assumptions and propose a solution? Thank you.
admin added the BugInvalid labels 2026-01-22 15:13:07 +01:00
admin closed this issue 2026-01-22 15:13:09 +01:00
Author
Owner

@alcaeus commented on GitHub (Aug 1, 2017):

The second call to persist is a no-op since the entity is already managed by the entity manager. It only has relevance if you're using an explicit change tracking policy, in which case it marks the entity for changeset computation.

Changes like these should be done in an onFlush handler since they require changeset recomputation.

@alcaeus commented on GitHub (Aug 1, 2017): The second call to `persist` is a no-op since the entity is already managed by the entity manager. It only has relevance if you're using an explicit change tracking policy, in which case it marks the entity for changeset computation. Changes like these should be done in an `onFlush` handler since they require changeset recomputation.
Author
Owner

@josefsabl commented on GitHub (Aug 2, 2017):

I resolved this by skipping doctrine events altogether and implemented custom DocumentManager that looks a bit like this:

class DocumentManager extends \Doctrine\ODM\MongoDB\DocumentManager {
	public function persist($document) {
		if ($document implements TValidation) {
			$document->validate();
		}
		parent::persist($document);
	}
}
@josefsabl commented on GitHub (Aug 2, 2017): I resolved this by skipping doctrine events altogether and implemented custom DocumentManager that looks a bit like this: ```PHP class DocumentManager extends \Doctrine\ODM\MongoDB\DocumentManager { public function persist($document) { if ($document implements TValidation) { $document->validate(); } parent::persist($document); } } ```
Author
Owner

@alcaeus commented on GitHub (Aug 2, 2017):

Oh, one more thing: this is The ORM repository, not ODM. Please open issues against doctrine/mongodb-odm in the future.

@alcaeus commented on GitHub (Aug 2, 2017): Oh, one more thing: this is The ORM repository, not ODM. Please open issues against doctrine/mongodb-odm in the future.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#5625