微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

单对一关系中的 Easy Admin 3 (Symfony 4) AssociationField 显示已关联的实体

如何解决单对一关系中的 Easy Admin 3 (Symfony 4) AssociationField 显示已关联的实体

在 Easy Admin 3 中使用 Symfony 4.4:
我有一对一的关系

class Usuario
{
...
    /**
     * @ORM\OnetoOne(targetEntity=Hora::class,inversedBy="usuario",cascade={"persist","remove"})
     */
    private $hora;
...
}
class Hora
{
...
    /**
     * @ORM\OnetoOne(targetEntity=Usuario::class,mappedBy="hora","remove"})
     */
    private $usuario;
...
}

我有一个用于 Usuario 的 CRUD 控制器:

class UsuarioCrudController extends AbstractCrudController
{
    public function configureFields(string $pageName): iterable
    {
    ...
    return [
    ...
            AssociationField::new('hora','Hora'),];

看起来一切正常,但是在“Usuario”的管理表单中,“hora”字段显示数据库中的所有值,甚至是已经分配给其他“Usuario”实体的值:
我希望下拉控件仅显示未分配的值,加上实际“Usuario”实体的值,以便控件易于使用。

使用easyadmin 执行此操作的正确方法是什么?

我已设法在 UsuarioCrudController 类中使用 $this->getDoctrine()->setFormTypeOptions([ "choices" => 对该字段进行编码,以仅显示未关联的“Hora”值,

但我无法访问正在管理的实际实体,也无法访问 UsuarioCrudController 类(也许那里无法访问)和 Usuario 类(我在这里尝试 __construct(EntityManagerInterface $entityManager) 无济于事,因为值不好像没有被注入,不知道为什么)。

解决方法

通过覆盖 EasyAdmin 方法或监听 EasyAdmin 事件,可以在 Easy admin 中自定义一些内容。

Example of methods

public function createIndexQueryBuilder(SearchDto $searchDto,EntityDto $entityDto,FieldCollection $fields,FilterCollection $filters): QueryBuilder
public function createEntity(string $entityFqcn)
public function createEditForm(EntityDto $entityDto,KeyValueStore $formOptions,AdminContext $context): FormInterface
//etc..

Example of events

use EasyCorp\Bundle\EasyAdminBundle\Event\AfterCrudActionEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityDeletedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityPersistedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityUpdatedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeCrudActionEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityDeletedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityPersistedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityUpdatedEvent;

您可以覆盖简单的 admin createEditFormBuildercreateNewFormBuilder 方法,这样您就可以访问当前表单数据并修改您的 hora 字段。

类似:

 use Symfony\Bridge\Doctrine\Form\Type\EntityType;
 use Symfony\Component\Form\FormBuilderInterface;
 use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
 use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore;
 
 public function createEditFormBuilder(EntityDto $entityDto,AdminContext $context): FormBuilderInterface {
    $formBuilder = parent::createEditFormBuilder($entityDto,$formOptions,$context);

    $unassignedValues = $this->yourRepo->findUnassignedValues();
    $data = $context->getEntity()->getInstance();
    if(isset($data) && $data->getHora()){
        //if your repo return an ArrayCollection
        $unassignedValues = $unassignedValues->add($data->getHora());
    }
    // if 'class' => 'App\Entity\Hora' is not passed as option,an error is raised (see //github.com/EasyCorp/EasyAdminBundle/issues/3095):
    //      An error has occurred resolving the options of the form "Symfony\Bridge\Doctrine\Form\Type\EntityType": The required option "class" is missing.
    $formBuilder->add('hora',EntityType::class,['class' => 'App\Entity\Hora','choices' => $unassignedValues]);

    return $formBuilder;
}

目前,easyadmin3 仍然缺乏文档,因此有时做某事的最佳方法是查看 admin 做事有多简单。

,

fwiw,可以在 Symfony easyadmin CrudController 的 configureFields() 方法 using 中访问正在编辑的实际实体:

if ( $pageName === 'edit' ) {
    ...
    $this->get(AdminContextProvider::class)->getContext()->getEntity()->getInstance()
    ...

这样在 configureFields() 中我可以添加代码来过滤我的实体:

            $horas_libres = $this->getDoctrine()->getRepository(Hora::class)->findAll();
            $horas_libres = array_filter( $horas_libres,function( $hora ) {
                    // select only "horas" not yet assigned
                    if ( $hora->getUsuario() === null )
                    {
                        return 1;
                    } else {
                        return 0;
                    }
                } );

然后添加实际的实体值,这正是我想要做的

array_unshift( $horas_libres,$this->get(AdminContextProvider::class)->getContext()->getEntity()->getInstance()->getHora() );

现在可以使用“choices”在返回的数组中构造该字段:

return [ ...
            AssociationField::new('hora','Hora')->setFormTypeOptions([
                "choices" => $horas_libres
            ]),]

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。