【问题标题】:How to use Symfony EasyAdmin with entities having a constructor?如何将 Symfony EasyAdmin 与具有构造函数的实体一起使用?
【发布时间】:2020-07-29 03:27:58
【问题描述】:

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

我倾向于将构造函数用于不可为空的实体属性。不幸的是,当我单击 e.g. 时,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在不实例化实体类的情况下显示“创建新实体对象”的形式?

【问题讨论】:

标签: symfony easyadmin


【解决方案1】:

不,EasyAdmin 本身不支持带参数的构造函数。

为了避免这个问题,你有三个解决方案。

解决方案 1:覆盖 EasyAdminController

The documentation explains this method.

// 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);

Solution3 在构造函数中接受空值。

我不喜欢这个解决方案。您的属性也应被编辑以接受空值,您的吸气剂应被编辑以返回空值。这是一个解决方案,但我不鼓励您使用它。

<?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;
    }

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

【讨论】:

  • 谢谢。不幸的是,解决方案 1 不是一个选项,因为两个构造函数参数 $title$company 是(部分)要由编辑器在表单中设置的数据。解决方案 2 可能有效,但我不确定我是否喜欢用静态 create() 方法替换构造函数。我同意避免使用解决方案 3。
  • 我理解您所说的关于解决方案2 的内容。经过多年的开发(和错误:)),我现在确信这不是在构造函数中添加参数的好习惯。当我在您的构造函数中添加参数时,您将我的业务模型与我的实体混合在一起,我现在避免使用它,因为实体只是在这里存储的。内部没有逻辑,只有 getter 和 setter。或者您可能会在使用 EasyAdmin 时遇到像这样的错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多