如何解决单对一关系中的 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;
...
}
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 中自定义一些内容。
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;
您可以覆盖简单的 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,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 举报,一经查实,本站将立刻删除。