in

Doctrine preUpdate event shows no changeset for associated collections


This is a question about the event system in Doctrine (within a Symfony project).

I have two classes, User and Visit, that are associated via a many-to-many relationship. I.e. a user can have many visits and a visit can have many users (that attend the visit).

class Visit 
{
    #[ORMColumn]
    protected string $Date;
    
    #[ORMManyToMany(targetEntity: User::class, inversedBy: "Visits")]
    #[ORMJoinTable(name: "users_visits")]
    protected Collection $Users;

    public function __construct()
    {        
        $this->Users = new ArrayCollection();
    }

    //... other properties and methods omitted
}

class User
{
    #[ORMColumn]
    protected string $Name;
    
    #[ORMManyToMany(targetEntity: Visit::class, inversedBy: "Users")]
    #[ORMJoinTable(name: "users_visits")]
    protected Collection $Visits;

    public function __construct()
    {        
        $this->Visits = new ArrayCollection();
    }

    //... other properties and methods omitted
}

I also have an UpdateSubscriber that is supposed to record certain inserts, updates or removals, in a separate sql-table to create an overview over all relevant changes later on.

class UpdateSubscriber implements EventSubscriberInterface
{
    public function __construct(private LoggerInterface $logger)
    {
    }

    public function getSubscribedEvents(): array
    {
        return [
            Events::preUpdate,
            Events::postPersist,
            Events::postRemove,
            Events::postFlush
        ];
    }

    public function preUpdate(PreUpdateEventArgs $args): void
    {
        $this->logger->debug('Something has been updated');
        if($args->hasChangedField('Users')){
            $this->logger->debug('It was the Users field');
        }
    }

    // ... other methods emitted

I have gotten this system to work, but when I run this test code

    $visitRepo = $this->om->getRepository(Visit::class);
    $userRepo = $this->om->getRepository(User::class);
    // you can assume that visit 7 and user 8 already exist in the database
    $v = $visitRepo->find(7);
    $u = $userRepo->find(8);
                
    $v->addUser($u);
    $this->om->flush();                

The test code works without errors and I can see a new row in the sql-table “users_visits”.

BUT: Checking the log I can only find “Something has been updated” but not “It was the Users field”. Using my debugging tools I can see that the EntityChangeSet is empty during preUpdate(), which is weird and unexpected.

I have extensively been reading the docs for the event PreUpdate but there is no mentioning of why changes to associated collections are not shown in the EntityChangeSet or how I could track those changes in an EventSubscriber.

Do I have to go via the rather cumbersome UnitOfWork during the onFlushEvent? Or this there something I have been missing?



Source: https://stackoverflow.com/questions/70556366/doctrine-preupdate-event-shows-no-changeset-for-associated-collections

Go library for writing standalone Map/Reduce jobs or for use with Hadoop’s streaming protocol

tkinter: how to inheret widgets from another .py file