EasyAdmin - Как правильно показать пользовательское свойство Entity, которое использует EntityRepository

Я хотел бы показать в EasyAdmin настраиваемое свойство, вот пример:

class Book
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Column(type="integer")
     */
    public $id;
    /**
     * @ORM\Column(type="string")
     */
    public $name;
    /**
     * @ORM\Column(type="float")
     */
    public $price;
    public function getBenefit(): float
    {
        // Here the method to retrieve the benefits
    }
}

В этом примере пользовательским параметром является benefit, это не параметр нашей сущности, и если мы настроим EasyAdmin таким образом, он будет работать!

easy_admin:
    entities:
        Book:
            class: App\Entity\Book
            list:
                fields:
                    - { property: 'title', label: 'Title' }
                    - { property: 'benefit', label: 'Benefits' }

Проблема в том, что если функция немного сложна и требует, например, EntityRepository, становится невозможным соблюдать Контроллер> Репозиторий> Сущности.

Есть ли у кого-нибудь обходной путь, возможно, с помощью AdminController для правильного отображения настраиваемых свойств в EasyAdmin?


person Martin Paucot    schedule 21.03.2019    source источник


Ответы (1)


Вы не должны помещать логику для извлечения преимуществ внутри сущности Book, особенно если она включает внешние зависимости, такие как entityManager.

Для этого вы, вероятно, могли бы использовать события Doctrine. Получите преимущества после загрузки Book сущности из БД. Сохраните преимущества до или после сохранения объекта Book в БД.

Подробнее об этом можно узнать здесь, https://symfony.com/doc/current/doctrine/event_listeners_subscribers.html

class Book
{
    ...
    public $benefits;
}
// src/EventListener/RetrieveBenefitListener.php
namespace App\EventListener;

use Doctrine\Common\Persistence\Event\LifecycleEventArgs;
use App\Entity\Book;

class RetrieveBenefitListener
{
    public function postLoad(LifecycleEventArgs $args)
    {
        $entity = $args->getObject();

        // only act on some "Book" entity
        if (!$entity instanceof Book) {
            return;
        }

        // Your logic to retrieve the benefits
        $entity->benefits = methodToGetTheBenefits();
    }
}
// src/EventListener/SaveBenefitListener.php
namespace App\EventListener;

use Doctrine\Common\Persistence\Event\LifecycleEventArgs;
use App\Entity\Book;

class SaveBenefitListener
{
    public function postUpdate(LifecycleEventArgs $args)
    {
        $entity = $args->getObject();

        // only act on some "Book" entity
        if (!$entity instanceof Book) {
            return;
        }

        // Your logic to save the benefits
        methodToSaveTheBenefits($entity->benefits);
    }
}
// services.yml
services:
    App\EventListener\RetrieveBenefitListener:
        tags:
            - { name: doctrine.event_listener, event: postLoad }
    App\EventListener\SaveBenefitListener:
        tags:
            - { name: doctrine.event_listener, event: postUpdate }

Это просто пример, я не тестировал код. Вам, вероятно, придется добавить логику для события postPersist, если вы создадите новые Book объекты.

В зависимости от логики получения преимуществ (другой вызов БД? Загрузка из внешнего API?), Вы можете захотеть подойти к проблеме по-другому (кэширование, загрузка их в вашу БД через задание cron, ...)

person thomas.drbg    schedule 21.03.2019