在symfony上使用EasyAdmin组件时新增带有关联实例的新实例时报错的解决方法

196 阅读1分钟

最近在使用 symfony 做一个简单的 web service ,在使用 Easy Admin Bundle 创建一个后端的数据库管理界面的时候遇到了一些问题,在这里分享一下解决的过程。

Symfony版本:5.1.14
EasyAdminBundle版本:3

/**
     * @var Tipoproducto
     *
     * @ORM\ManyToOne(targetEntity="Tipoproducto", inversedBy="id")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="idTipo", referencedColumnName="id")
     * })
     */
    private $idtipo;

    /**
     * @var Precio
     *
     * @ORM\ManyToOne(targetEntity="Precio")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="idPrecio", referencedColumnName="id")
     * })
     */
    private $idprecio;

我的商品表有两个外键属性分别是类别和价格,其映射到Doctrine后的实体如上图。这两个外键在实体中都以一个对象的形式在存储和查询,问题在于如果我们直接照着官方教程来设计这个实体的管理界面,在列表可以正常显示实体链接但是在尝试添加的时候会报错

public function configureFields(string $pageName): iterable
    {
        return [
            IdField::new('id')->hideOnForm(),
            TextField::new('nombre'),
            TextareaField::new('descripcion'),
            IntegerField::new('stock'),
            TextField::new('foto'),
            AssociationField::new('idtipo', 'Tipo'),
            AssociationField::new('idprecio', 'Precio'),
        ];
    }

image.png 这里提示idTipo属性需要一个Tipo的实例但是返回的却是null,这是因为我们没有在创建商品实例的时候指定这两个外键属性的实例类型导致他找不到对应的实例。

我们可以在 官方文档 里看到,想要在CRUD控制器重写 createEntity() 方法来让控制器在新建一个实例的时候由我们更改新实例的初始化选项。

public function createEntity(string $entityFqcn)
    {
        $product = new Producto();
        $precio=new Precio();
        $tipo=new Tipoproducto();
        $precio=$this->getDoctrine()->getRepository(Precio::class)->findOneBy(['id' => '1']);
        $product->setIdprecio($precio);
        $tipo=$this->getDoctrine()->getRepository(Tipoproducto::class)->findOneBy(['id' => '1']);
        $product->setIdtipo($tipo);
        return $product;
    }

我们重写这个方法,并且在方法里指定外键属性的初始值为相应实体的一个实例对象,来让新实例可以顺利的找到自己的属性可以在哪个实体里去寻找

image.png 重新访问界面,我们可以看到没有出错并且外键属性也能正确读到其他实体,这样问题就解决了。

因为我虽然按照教程来一步步的做却还是碰到了错误,在国内和外网找了很久也没有找到解决方法,所以解决后就想把这个错误记录下来,这次的错误有可能是因为我的 Doctrine 实体是由外部数据库导入而产生的bug,希望可以帮助到有需要的人。