Как использовать Symfony EasyAdmin с объектами, имеющими конструктор?

Поддерживает ли EasyAdmin классы сущностей с аргументами конструктора для свойств, которые не допускают значения NULL? EasyAdmin создает экземпляр класса сущности, даже если вы нажмете кнопку «Добавить», верно? К сожалению, это приводит к ошибке «Слишком мало аргументов для функции __construct ()». У вас есть решение этой проблемы?

Я обычно использую конструктор для свойств сущности, которые не допускают значения NULL. К сожалению, EasyAdmin выдает подобные ошибки, когда я нажимаю, например, Add FiscalYear кнопка для создания нового объекта сущности (FiscalYear в моем примере):

Too few arguments to function App\Entity\FiscalYear::__construct(), 0 passed in /myProject/vendor/easycorp/easyadmin-bundle/src/Controller/AdminControllerTrait.php on line 618 and exactly 2 expected

Как я могу предотвратить эти ошибки? Как вы можете видеть в следующем классе сущностей, два аргумента конструктора представляют данные, которые должны быть отправлены через форму:

<?php
declare(strict_types=1);
namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\FiscalYearRepository")
 */
class FiscalYear
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private ?int $id = null;

    /**
     * @ORM\Column(type="integer")
     */
    private int $title;

    /**
     * @ORM\Column(type="boolean", options={"default": 0})
     */
    private bool $completed = false;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Company", inversedBy="fiscalYears")
     * @ORM\JoinColumn(nullable=false)
     */
    private Company $company;

    public function __construct(int $title, Company $company)
    {
        $this->title = $title;
        $this->company = $company;
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getTitle(): int
    {
        return $this->title;
    }

    public function setTitle(int $title): void
    {
        $this->title = $title;
    }

    public function getCompleted(): bool
    {
        return $this->completed;
    }

    public function setCompleted(bool $completed): void
    {
        $this->completed = $completed;
    }

    public function getCompany(): Company
    {
        return $this->company;
    }

    public function setCompany(Company $company): void
    {
        $this->company = $company;
    }
}

Есть ли возможность позволить EasyAdmin отображать форму «создать новый объект сущности» без создания экземпляра класса сущности?


person Mark Watney    schedule 16.04.2020    source источник
comment
Это не кажется полезным вариантом: symfony.com/doc/current/bundles/EasyAdminBundle/book/   -  person Mark Watney    schedule 16.04.2020


Ответы (1)


Нет, EasyAdmin изначально не поддерживает конструктор с аргументом.

Чтобы избежать этой проблемы, у вас есть три решения.

решение1: переопределить EasyAdminController

В документации объясняется этот метод.

// src/Controller/AdminController.php
namespace App\Controller;

use EasyCorp\Bundle\EasyAdminBundle\Controller\EasyAdminController;

class FiscalYearController extends EasyAdminController
{
    public function createNewFiscalYearEntity()
    {
        //your own logic here to retrieve title and company
        return new FiscalYear($title, $company);
    }
}

В зависимости от вашей бизнес-модели получить название и компанию может быть очень сложно.

решение2: соблюдайте шаблон сущности и помогите своей бизнес-модели с шаблоном фабрики

  1. Ваши сущности должны соблюдать шаблон сущности, а их конструктор должен быть отредактирован для удаления аргументов.
  2. Чтобы заменить конструктор в бизнес-модели, создайте фабрику.
class FiscalYearFactory 
{
   public static function create(int $title, Company $company): FiscalYear
   {
       $fiscalYear = new FiscalYear();
       $fiscalYear->setCompany($company);
       $fiscalYear->setTitle($title);

       return $fiscalYear;
   }
}

в вашей модели вам нужно сделать некоторые обновления:

//Comment code like this in your business model
$fiscalYear = new FiscalYear(2020,$company);
//Replace it, by this code:
$fiscalYear = FiscalYearFactory::create(2020,$company);

Решение3. Примите в конструкторе нулевые значения.

Мне это решение НЕ нравится. Ваши свойства также должны быть отредактированы, чтобы принимать нулевые значения, ваши геттеры должны быть отредактированы, чтобы возвращать нулевое значение. Это решение, но я не рекомендую вам его использовать.

<?php
declare(strict_types=1);
namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\FiscalYearRepository")
 */
class FiscalYear
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private ?int $id = null;

    /**
     * @ORM\Column(type="integer")
     */
    private ?int $title;

    /**
     * @ORM\Column(type="boolean", options={"default": 0})
     */
    private bool $completed = false;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Company", inversedBy="fiscalYears")
     * @ORM\JoinColumn(nullable=false)
     */
    private Company $company;

    public function __construct(?int $title = null, ?Company $company = null)
    {
        $this->title = $title;
        $this->company = $company;
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getTitle(): ?int
    {
        return $this->title;
    }

Вам следует использовать первое решение, которое лучше

person Alexandre Tranchant    schedule 16.04.2020
comment
Спасибо. К сожалению, решение 1 не является вариантом, потому что два аргумента конструктора $title и $company являются (частью) данными, которые должны быть установлены в форме редактором. Решение 2 может сработать, но я не уверен, хочу ли я заменить конструктор статическим методом create(). Я согласен с тем, что решения 3 следует избегать. - person Mark Watney; 16.04.2020
comment
Я понимаю, что вы сказали о решении2. После нескольких лет разработки (и ошибок :)) я теперь убежден, что добавлять аргументы в конструктор - не лучшая практика. Когда я добавлял аргументы в ваши конструкторы, вы смешивали мою бизнес-модель с моими сущностями, и я избегаю этого сейчас, потому что сущности предназначены только для хранения. Никакой логики внутри, только геттеры и сеттеры. Или вы могли столкнуться с ошибками, подобными этой, с EasyAdmin. - person Alexandre Tranchant; 16.04.2020