首页 > 解决方案 > 如何将 Symfony EasyAdmin 与具有构造函数的实体一起使用?

问题描述

EasyAdmin 是否支持具有不可为空属性的构造函数参数的实体类?即使您单击“添加”按钮,EasyAdmin 也会实例化实体类,对吗?不幸的是,这会导致“函数__construct() 的参数太少”错误。你有解决这个问题的方法吗?

我倾向于将构造函数用于不可为空的实体属性。不幸的是,当我单击 egAdd FiscalYear按钮创建一个新的实体对象(FiscalYear在我的示例中)时,EasyAdmin 会引发类似这样的错误:

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 在不实例化实体类的情况下显示“创建新实体对象”表单?

标签: symfonyeasyadmin

解决方案


不,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;
    }

您应该使用第一个解决方案,这是一种更好的做法


推荐阅读