DDC-971: PersistentCollection->clear() not working when first received from database #1215

Closed
opened 2026-01-22 13:06:10 +01:00 by admin · 9 comments
Owner

Originally created by @doctrinebot on GitHub (Jan 6, 2011).

Originally assigned to: @beberlei on GitHub.

Jira issue originally created by user digonator:

I have attached my mappings and objects for reference

Basically, I have a DAO that fetches my ContractTemplate object from the database by the id.

In my controller, I use the DAO to fetch the object.

public function getById($id) {
    return $this->em->find($this->className, $id);
}

Once I get the object back, I want to clear all of the layoutBands from the template object so I run the following

$template = $templateDao->getById(5);
$template->getLayoutBands()->clear();
$templateDao->save($template);

This does not remove the layout bands from the database.

However, if I run an initialize (or anything in the PersistentCollection class that runs the initialize, ie count(), isEmpty(), etc ) before I run the clear then it works properly. For instance

$template = $templateDao->getById(5);
$template->getLayoutBands()->initialize(); // OR $template->getLayoutBands()->count()
$template->getLayoutBands()->clear();
$templateDao->save($template);

I took a look at the PersistentCollection class and in the clear function it runs the following code first

if ($this->initialized && $this->isEmpty()) {

Because my collection is loaded lazily, it is not initialized, and it never hits the isEmpty() call...

Is this something that I have wrong with my mapping? or the way I am doing things? Like I mentioned above, I can get around it my running the initialize first, but I dont think I should have to do that if I just want to clear the collection

Originally created by @doctrinebot on GitHub (Jan 6, 2011). Originally assigned to: @beberlei on GitHub. Jira issue originally created by user digonator: I have attached my mappings and objects for reference Basically, I have a DAO that fetches my ContractTemplate object from the database by the id. In my controller, I use the DAO to fetch the object. ``` public function getById($id) { return $this->em->find($this->className, $id); } ``` Once I get the object back, I want to clear all of the layoutBands from the template object so I run the following ``` $template = $templateDao->getById(5); $template->getLayoutBands()->clear(); $templateDao->save($template); ``` This does not remove the layout bands from the database. However, if I run an initialize (or anything in the PersistentCollection class that runs the initialize, ie count(), isEmpty(), etc ) before I run the clear then it works properly. For instance ``` $template = $templateDao->getById(5); $template->getLayoutBands()->initialize(); // OR $template->getLayoutBands()->count() $template->getLayoutBands()->clear(); $templateDao->save($template); ``` I took a look at the PersistentCollection class and in the clear function it runs the following code first ``` if ($this->initialized && $this->isEmpty()) { ``` Because my collection is loaded lazily, it is not initialized, and it never hits the isEmpty() call... Is this something that I have wrong with my mapping? or the way I am doing things? Like I mentioned above, I can get around it my running the initialize first, but I dont think I should have to do that if I just want to clear the collection
admin added the Bug label 2026-01-22 13:06:10 +01:00
admin closed this issue 2026-01-22 13:06:11 +01:00
Author
Owner

@doctrinebot commented on GitHub (Jan 13, 2011):

Comment created by pem:

I seem to have the same problem on oneToMany unidirectional collections (@manyToMany)
once using a count or accessing the collection items, the clear works as expected. Otherwise the clear() is ignored.

@doctrinebot commented on GitHub (Jan 13, 2011): Comment created by pem: I seem to have the same problem on oneToMany unidirectional collections (@manyToMany) once using a count or accessing the collection items, the clear works as expected. Otherwise the clear() is ignored.
Author
Owner

@doctrinebot commented on GitHub (Jan 13, 2011):

Comment created by @beberlei:

Various people reported bugs of that sort. But i couldnt ever reproduce them. Could any of you please add an xdebug function trace around the code?

xdebug*start*trace("/tmp/doctrine");

You can send me that trace by e-mail kontakt@beberlei.de

@doctrinebot commented on GitHub (Jan 13, 2011): Comment created by @beberlei: Various people reported bugs of that sort. But i couldnt ever reproduce them. Could any of you please add an xdebug function trace around the code? ``` xdebug*start*trace("/tmp/doctrine"); ``` You can send me that trace by e-mail kontakt@beberlei.de
Author
Owner

@doctrinebot commented on GitHub (Jan 13, 2011):

Comment created by @beberlei:

Btw, the line:

if ($this->initialized && $this->isEmpty()) {

is not relevant here, it is not true in your case, because initialized is false. So the return is not executed here.

@doctrinebot commented on GitHub (Jan 13, 2011): Comment created by @beberlei: Btw, the line: ``` if ($this->initialized && $this->isEmpty()) { ``` is not relevant here, it is not true in your case, because initialized is false. So the return is not executed here.
Author
Owner

@doctrinebot commented on GitHub (Jan 13, 2011):

Comment created by @beberlei:

Another thing, but i think both of you are doing it right - the clear() only works against the database if you are on the owning side, so this does not work with "plain" one-to-many associations.

@doctrinebot commented on GitHub (Jan 13, 2011): Comment created by @beberlei: Another thing, but i think both of you are doing it right - the clear() only works against the database if you are on the owning side, so this does not work with "plain" one-to-many associations.
Author
Owner

@doctrinebot commented on GitHub (Jan 13, 2011):

Comment created by digonator:

I sent the trace to you Benjamin

Let me know if you need anything else from me

@doctrinebot commented on GitHub (Jan 13, 2011): Comment created by digonator: I sent the trace to you Benjamin Let me know if you need anything else from me
Author
Owner

@doctrinebot commented on GitHub (Feb 13, 2011):

Comment created by @beberlei:

Reformated

@doctrinebot commented on GitHub (Feb 13, 2011): Comment created by @beberlei: Reformated
Author
Owner

@doctrinebot commented on GitHub (Feb 13, 2011):

Comment created by @beberlei:

@Mike you are not calling PersistentCollection->clear() on the owning side of the association. That means the change is not persisted into the database.

@doctrinebot commented on GitHub (Feb 13, 2011): Comment created by @beberlei: @Mike you are not calling PersistentCollection->clear() on the owning side of the association. That means the change is not persisted into the database.
Author
Owner

@doctrinebot commented on GitHub (Feb 13, 2011):

Issue was closed with resolution "Invalid"

@doctrinebot commented on GitHub (Feb 13, 2011): Issue was closed with resolution "Invalid"
Author
Owner

@doctrinebot commented on GitHub (Feb 14, 2011):

Comment created by digonator:

This is fine, but I am not calling it from the owing side.
According to http://www.doctrine-project.org/docs/orm/2.0/en/reference/association-mapping.html
"The many side of OneToMany/ManyToOne bidirectional relationships must be the owning side"

I am calling it from the inverse side.
In the above example, this means that layoutbands is the owning side of the relationship and I am calling $template->getLayoutBands()->clear()... from the $template side

To simplify my example, what if I had the following?

Two objects
User and Address
A user has a oneToMany relationship with address

My mappings are

User

$metadata->mapOneToMany(array(
    'fieldName' => 'addresses',
    'cascade' => array('persist','remove'),
    'orphanRemoval' => true,
    'targetEntity' => "Entities\Address",
    'mappedBy' => "user"
));

Address

$metadata->mapManyToOne(array(
    'fieldName' => 'user',
    'inversedby' => 'users',
    'targetEntity' => 'Entities\User',
    'cascade' => array('persist'),
    'joinColumns' => array(
        'joinColumn' => array(
            'name' => "userId",
            'referencedColumnName' => "userId"
        )
    )
));

With this example, the user is the inverse, and the address is the owning.

If I call $user->getAddresses()->clear() and then save the user, the addresses remain in the database when they should not

@doctrinebot commented on GitHub (Feb 14, 2011): Comment created by digonator: This is fine, but I am not calling it from the owing side. According to http://www.doctrine-project.org/docs/orm/2.0/en/reference/association-mapping.html "The many side of OneToMany/ManyToOne bidirectional relationships must be the owning side" I am calling it from the inverse side. In the above example, this means that layoutbands is the owning side of the relationship and I am calling $template->getLayoutBands()->clear()... from the $template side To simplify my example, what if I had the following? Two objects User and Address A user has a oneToMany relationship with address My mappings are User ``` $metadata->mapOneToMany(array( 'fieldName' => 'addresses', 'cascade' => array('persist','remove'), 'orphanRemoval' => true, 'targetEntity' => "Entities\Address", 'mappedBy' => "user" )); ``` Address ``` $metadata->mapManyToOne(array( 'fieldName' => 'user', 'inversedby' => 'users', 'targetEntity' => 'Entities\User', 'cascade' => array('persist'), 'joinColumns' => array( 'joinColumn' => array( 'name' => "userId", 'referencedColumnName' => "userId" ) ) )); ``` With this example, the user is the inverse, and the address is the owning. If I call $user->getAddresses()->clear() and then save the user, the addresses remain in the database when they should not
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#1215