Calcul d'une propriété virtuelle d'une entité Doctrine suite à son chargement

Publié le 15/05/2021 • Mis à jour le 15/05/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 calculer la valeur d'un champ virtuel d'une entité Doctrine juste après con chargement. Nous utilisons l'événement Doctrine postLoad. Bien sûr, ici un simple accesseur suffirait. L'écouteur d'événements est indispensable quand on a besoin d'injecter un service comme c'est fait dans cet exemple (même si je n'utilise pas le service injecté). La propriété iri est déclarée comme ceci :

/**
  * Propriété pour le snippet 147.
  *
  * @var ?string IRI API Platform de la ressource (example factice)
  */
 protected ?string $iri = null;
Retrouvez un squelette d'écouteur d'événements Doctrine complet dans ce snippet.


<?php

/** @noinspection PhpPropertyOnlyWrittenInspection */

// src/Doctrine/Listener/ArticleListener.php

declare(strict_types=1);

namespace App\Doctrine\Listener;

use App\Entity\Article;
use App\Repository\ArticleRepository;

class ArticleListener
{
    private ArticleRepository $articleRepository;

    public function __construct(ArticleRepository $articleRepository)
    {
        $this->articleRepository = $articleRepository;
    }

    /**
     * This is a dummy example.
     */
    public function postLoad(Article $article): void
    {
        $article->setIri('/articles/'.$article->getId());
    }
}
En bonus, le snippet permettant d'utiliser ce code : 🎉
<?php

declare(strict_types=1);

// src/Controller/Snippet/Snippet147Trait.php

namespace App\Controller\Snippet;

use App\Repository\ArticleRepository;

/**
 * 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 ArticleRepository $articleRepo
 */
trait Snippet147Trait
{
    /**
     * @noinspection OneTimeUseVariablesInspection
     */
    public function snippet147(): void
    {
        $article = $this->articleRepo->findById(147);

        echo $article->getIri(); // The IRI is computed in the Article listener

        // 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\Repository\ArticleRepository;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;

/**
 * @covers Snippet147Trait
 */
final class Snippet147Test extends KernelTestCase
{
    private ArticleRepository $articleRepo;

    protected function setUp(): void
    {
        self::bootKernel();
        $this->articleRepo = self::getContainer()->get(ArticleRepository::class);
    }

    /**
     * @covers ArticleListener::postLoad
     */
    public function testSnippet147(): void
    {
        $article = $this->articleRepo->findById(147);
        self::assertSame('/articles/147', $article->getIri());
    }
}