Easy Admin 3 (Symfony 4) OneToOne 关系中的 AssociationField 显示已经关联的实体
Easy Admin 3 (Symfony 4) AssociationField in OneToOne relationship shows already associated entities
将 Symfony 4.4 与 Easy Admin 3 结合使用:
我有一对一关系
class Usuario
{
...
/**
* @ORM\OneToOne(targetEntity=Hora::class, inversedBy="usuario", cascade={"persist", "remove"})
*/
private $hora;
...
}
class Hora
{
...
/**
* @ORM\OneToOne(targetEntity=Usuario::class, mappedBy="hora", cascade={"persist", "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 class、
中使用 $this->getDoctrine()
和 ->setFormTypeOptions([ "choices" =>
对字段进行编码以仅显示未关联的“Hora”值
但我无法访问正在管理的实际实体,也无法访问 UsuarioCrudController class(也许那里无法访问),也无法访问 Usuario class(我在这里尝试过 __construct(EntityManagerInterface $entityManager)
无济于事,因为似乎没有注入值,不知道为什么)。
可以通过覆盖 EasyAdmin 方法或侦听 EasyAdmin 事件来自定义 easyadmin 中的一些内容。
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..
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;
您可以覆盖 easy admin createEditFormBuilder
或 createNewFormBuilder
方法,这样您就可以访问当前表单数据并修改您的 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, KeyValueStore $formOptions, 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 仍然缺少文档,所以有时做某事的最好方法是查看管理员做事的难易程度。
首先,可以在 Symfony easyadmin CrudController 的 configureFields() 方法中访问正在编辑的实际实体 using:
if ( $pageName === 'edit' ) {
...
$this->get(AdminContextProvider::class)->getContext()->getEntity()->getInstance()
...
通过这种方式,我可以在 configureFields() 中添加代码来过滤我的实体:
$horas_libres = $this->getDoctrine()->getRepository(Hora::class)->findFree();
然后添加实际的实体值,这正是我想要做的:
array_unshift( $horas_libres,
$this->get(AdminContextProvider::class)->getContext()->getEntity()->getInstance()->getHora() );
现在可以使用“选择”在返回的数组中构造字段:
return [ ...
AssociationField::new('hora', 'Hora')->setFormTypeOptions([
"choices" => $horas_libres
]),
]
将 Symfony 4.4 与 Easy Admin 3 结合使用:
我有一对一关系
class Usuario
{
...
/**
* @ORM\OneToOne(targetEntity=Hora::class, inversedBy="usuario", cascade={"persist", "remove"})
*/
private $hora;
...
}
class Hora
{
...
/**
* @ORM\OneToOne(targetEntity=Usuario::class, mappedBy="hora", cascade={"persist", "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 class、
中使用$this->getDoctrine()
和 ->setFormTypeOptions([ "choices" =>
对字段进行编码以仅显示未关联的“Hora”值
但我无法访问正在管理的实际实体,也无法访问 UsuarioCrudController class(也许那里无法访问),也无法访问 Usuario class(我在这里尝试过 __construct(EntityManagerInterface $entityManager)
无济于事,因为似乎没有注入值,不知道为什么)。
可以通过覆盖 EasyAdmin 方法或侦听 EasyAdmin 事件来自定义 easyadmin 中的一些内容。
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..
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;
您可以覆盖 easy admin createEditFormBuilder
或 createNewFormBuilder
方法,这样您就可以访问当前表单数据并修改您的 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, KeyValueStore $formOptions, 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 仍然缺少文档,所以有时做某事的最好方法是查看管理员做事的难易程度。
首先,可以在 Symfony easyadmin CrudController 的 configureFields() 方法中访问正在编辑的实际实体 using:
if ( $pageName === 'edit' ) {
...
$this->get(AdminContextProvider::class)->getContext()->getEntity()->getInstance()
...
通过这种方式,我可以在 configureFields() 中添加代码来过滤我的实体:
$horas_libres = $this->getDoctrine()->getRepository(Hora::class)->findFree();
然后添加实际的实体值,这正是我想要做的:
array_unshift( $horas_libres,
$this->get(AdminContextProvider::class)->getContext()->getEntity()->getInstance()->getHora() );
现在可以使用“选择”在返回的数组中构造字段:
return [ ...
AssociationField::new('hora', 'Hora')->setFormTypeOptions([
"choices" => $horas_libres
]),
]