Récupérer l'ensemble des modifications d'une entité Doctrine après une mise à jour

Publié le 21/04/2021 • Mis à jour le 21/04/2021


English language detected! 🇬🇧

  We noticed that your browser is using English. Do you want to read this post in this language?

Read the english version 🇬🇧 Close

Dans ce bout de code, nous voyons comment récupérer l'ensemble des modifications d'une entité Doctrine après une mise à jour. C'est quelque chose d'essentiel à savoir quand on utilise Doctrine. Typiquement, après une mise à jour, on peut avoir besoin de déclencher certains traitements qui dépendent d'un statut ou d'une valeur modifiée. On peut lever un événement qui va déclencher tous les traitements voulus pour notre cas fonctionnel. Dans la seconde partie du snippet, on voit comment détecter le statut actuel de l'entité du point de vue de l'ORM.


<?php

declare(strict_types=1);

// src/Controller/Snippet/Snippet142Trait.php

namespace App\Controller\Snippet;

use App\Data\ArticleData;
use App\Entity\Article;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\UnitOfWork;

/**
 * J'utilise un trait PHP afin d'isoler chaque snippet dans un fichier.
 * Ce code doit être apellé d'un contrôleur Symfony étendant AbstractController (depuis Symfony 4.2)
 * ou Symfony\Bundle\FrameworkBundle\Controller\Controller (Symfony <= 4.1).
 * Les services sont injectés dans le constructeur du contrôleur principal.
 *
 * @property ArticleData $articleData
 */
trait Snippet142Trait
{
    public function snippet142(): void
    {
        $manager = $this->getDoctrine()->getManager();
        if (!$manager instanceof EntityManager) {
            throw new \RuntimeException('Houston, We Have a Problem. 💥');
        }

        // Get the current snippet
        $snippet = $this->articleData->getArticleById(142);

        // Get the unit of work object
        $uow = $manager->getUnitOfWork();

        // Modify a field
        $snippet->setAuthor('Tintin'.random_int(1, 99));

        // Compute all changesets
        $uow->computeChangeSets();

        // Or for this entity only
        $uow->computeChangeSet($manager->getClassMetadata(Article::class), $snippet);

        // Then get it, we have the field modified as the key which has for value
        // an array with the old as first item and new value as the second item
        // try it!
        $changeset = $uow->getEntityChangeSet($snippet);

        var_dump($changeset);

        // And what is the state of this entity? 🧐
        switch ($uow->getEntityState($snippet)) {
            case UnitOfWork::STATE_MANAGED:
                echo 'Snippet is managed (already in DB).';
                break;
            case UnitOfWork::STATE_REMOVED:
                echo 'Snippet is going to be removed.';
                break;
            case UnitOfWork::STATE_DETACHED:
                echo 'Snippet is detached.';
                break;
            case UnitOfWork::STATE_NEW:
                echo 'Snippet is new.';
                break;
        }

        // That's it! 😁
    }
}

 Exécuter le snippet  ≪ this.showUnitTest ? this.trans.hide_unit_test : this.trans.show_unit_test ≫  Plus sur Stackoverflow   Lire la doc  Plus sur le web

<?php

declare(strict_types=1);

namespace App\Tests\Controller\Snippets;

use App\Data\ArticleData;
use Doctrine\Bundle\DoctrineBundle\Registry;
use Doctrine\ORM\EntityManager;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;

/**
 * @covers Snippet142Trait
 */
final class Snippet142Test extends KernelTestCase
{
    private Registry $doctrine;
    private ArticleData $articleData;

    protected function setUp(): void
    {
        self::bootKernel();
        $this->doctrine = self::getContainer()->get('doctrine');
        $this->articleData = self::getContainer()->get(ArticleData::class);
    }

    /**
     * @covers Snippet142Trait::snippet142
     */
    public function testSnippet142(): void
    {
        $manager = $this->doctrine->getManager();
        if (!$manager instanceof EntityManager) {
            throw new \RuntimeException('Houston, We Have a Problem. 💥');
        }

        $uow = $manager->getUnitOfWork();
        $snippet = $this->articleData->getArticleById(142);
        $snippet->setAuthor('Tintin');
        $uow->computeChangeSets();
        $changeset = $uow->getEntityChangeSet($snippet);

        self::assertIsArray($changeset);
        self::assertArrayHasKey('author', $changeset);
        self::assertSame('COil', $changeset['author'][0]);
        self::assertSame('Tintin', $changeset['author'][1]);
    }
}