Symfony SonataAdmin绑定链接字段(级联选择)

Symfony SonataAdmin绑定链接字段(级联选择),symfony,sonata-admin,Symfony,Sonata Admin,我正在尝试使用sonata管理包创建链接下拉列表 有 产品 产品类别多对多产品 与产品类别关联的产品功能基数:与产品关联的多对多和与类别关联的多对一,即一个类别可以有多个功能,但一个功能与一个类别关联 一切正常,一个“类别”字段的多选启用组合框和另一组“产品功能”字段的复选框正在使用此选项显示 在产品输入表格中: protected function configureFormFields(FormMapper $formMapper) { $formMapper

我正在尝试使用sonata管理包创建链接下拉列表

产品

产品类别多对多产品

与产品类别关联的产品功能基数:与产品关联的多对多和与类别关联的多对一,即一个类别可以有多个功能,但一个功能与一个类别关联

一切正常,一个“类别”字段的多选启用组合框和另一组“产品功能”字段的复选框正在使用此选项显示

在产品输入表格中:

  protected function configureFormFields(FormMapper $formMapper)
    {
        $formMapper            
    ->add('category', 'sonata_type_model', array('required' => false, 'expanded' => false, 'multiple' => true, 'label' => 'Choose your categories'))
   ->add('features', 'sonata_type_model', array('required' => false, 'expanded' => true, 'multiple' => true, 'label' => 'Choose Features'))
但我想要的是,当我在第一个组合(即类别)中选择值时,第二个复选框列表(即特征)应相应地动态加载,只有与该类别链接的特征

由于第一个选择框启用了多选功能,因此第二个列表是累积的将更好,即当选择类别1时,将显示与类别1相关的功能 然后,当选择类别2且同时选择类别1时,将显示与类别1和类别2相关的功能

我怎么做

我一直在谷歌上搜索,我找到的唯一好答案是这个2年前的解决方案,它看起来相当长而且有点陈旧。还有其他解决办法吗?在过去的两年中,事情一定发生了变化,因为在这段时间内发布了几个版本的sonata admin

有什么帮助吗?
提前谢谢。

我在这方面有很多困难,但我想我找到了一个可行的解决办法。希望这能为将来节省一些时间

我的案例是:我有多个公司实体,有1到n个联系人实体。创建新职务时,我必须选择公司,然后我要按所选公司筛选联系人列表。正如你所看到的,它起作用了。根据所选公司,如果已加载联系人,则匹配列表:

为了让这一切顺利进行,我刚刚禁用了Customer和ContactPerson的映射标志,以便自己在postPersist中映射数据,并在我的admin类Extendes BaseAdmin中设置了postUpdate

然后,我为我的所有公司实体使用sonata_type_choice_field_mask。我自己构建了一个数据数组。之后,我使用sonata_type_模型,通过传递匹配的filter ContactPerson下拉列表,添加了一个预过滤

这是非常好的工作-但当然,它将失败,如果你有成千上万的公司和客户。在我的情况下,这不会发生,因此这是一个切实可行的解决方案

代码删除了不必要的内容:

<?php

namespace AppBundle\Admin;

use AppBundle\Entity\Customer;
use AppBundle\Entity\Job;
use AppBundle\Form\Types;
use AppBundle\Repository\CustomerRepository;
use AppBundle\Service\EntityManager;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Route\RouteCollection;
use Sonata\AdminBundle\Show\ShowMapper;

class JobAdmin extends BaseAdmin
{
    const CONTACT_PERSON_DROPDOWN_PREFIX = 'contactPersons';

    /**
     * @param Job $job
     * @return null|string
     */
    protected function getPreselectedCustomerId(Job $job)
    {
        if ($job) {
            $customer = $job->getCustomer();

            if ($customer) {
                $customerId = $customer->getId();

                return $customerId;
            }
        }

        return null;
    }

    /**
     * @return \Doctrine\ORM\EntityRepository
     */
    protected function getEnabledCustomers()
    {
        $customerRepository = $this->getCustomerRepository();
        $customers          = $customerRepository->findByEnabled();

        return $customers;
    }

    /**
     * @param $enabledCustomers
     * @return array
     */
    protected function getFilterMap($enabledCustomers)
    {
        $filterMap = [];

        /**
         * @var $customer Customer
         */
        foreach ($enabledCustomers as $customer) {
            $customerId             = $customer->getId();
            $fieldName              = self::CONTACT_PERSON_DROPDOWN_PREFIX . $customerId;
            $filterMap[$customerId] = [$fieldName];
        }

        return $filterMap;
    }

    /**
     * @param $enabledCustomers
     * @return array
     */
    protected function getCustomerDropDown($enabledCustomers)
    {
        $customerDropDown = [];

        /**
         * @var $customer Customer
         */
        foreach ($enabledCustomers as $customer) {
            $customerId              = $customer->getId();
            $name                    = $customer->getName();
            $customerDropDown[$name] = $customerId;
        }

        return $customerDropDown;
    }

    /**
     * @param Customer $customer
     * @return \Doctrine\ORM\QueryBuilder
     */
    protected function getFilterQueryForCustomer(Customer $customer)
    {
        $entityManager      = $this->getEntityManager();
        $contactPersonQuery = $entityManager->createQueryBuilder('cp')
            ->select('cp')
            ->from('AppBundle:ContactPerson', 'cp')
            ->where('cp.customer = :customer')
            ->setParameter('customer', $customer)
            ->orderBy('cp.name', 'ASC')
        ;

        return $contactPersonQuery;
    }

    /**
     * @param FormMapper $formMapper
     */
    protected function configureFormFields(FormMapper $formMapper)
    {
        $job              = $this->getSubject();
        $enabledCustomers = $this->getEnabledCustomers();
        $filterMap        = $this->getFilterMap($enabledCustomers);
        $customerDropDown = $this->getCustomerDropDown($enabledCustomers);
        $preselectedId    = $this->getPreselectedCustomerId($job);

        $formMapper
            ->tab('BaseData')
                ->with('JobData')
                    ->add('customer', 'sonata_type_choice_field_mask', array(
                        'choices'      => $customerDropDown,
                        'data'         => $preselectedId,
                        'map'          => $filterMap,
                        'by_reference' => false,
                        'required'     => true,
                        'mapped'       => false,
                        )
                    )
                ->end()
            ->end()
        ;

        /**
         * @var $customer Customer
         */
        foreach ($enabledCustomers as $customer) {
            $customerId  = $customer->getId();
            $fieldName   = self::CONTACT_PERSON_DROPDOWN_PREFIX . $customerId;
            $filterQuery = $this->getFilterQueryForCustomer($customer);

            $formMapper
                ->tab('BaseData')
                    ->with('JobData')
                        ->add($fieldName, 'sonata_type_model', array(
                            'class'  => 'AppBundle\Entity\ContactPerson',
                            'query'  => $filterQuery,
                            'mapped' => false,
                            'label'  => 'Contact Person'
                        ))
                    ->end()
                ->end()
            ;
        }

        $formMapper
            ->tab('BaseData')
                ->with('JobData')
                    ->add('name')
                    // Add more fields
                ->end()
            ->end()
        ;
    }

    /**
     * @param EntityManager $entityManager
     * @return \Doctrine\ORM\EntityRepository
     */
    protected function getCustomerRepository(EntityManager $entityManager = null)
    {
        if (!$entityManager) {
            $entityManager = $this->getEntityManager();
        }

        $customerRepository = $entityManager->getRepository(Customer::class);

        return $customerRepository;
    }

    /**
     * @return EntityManager
     */
    protected function getEntityManager()
    {
        $entityManager = $this->getConfigurationPool()->getContainer()->get('doctrine')->getManager();

        return $entityManager;
    }

    /**
     * @param Job $job
     */
    protected function mapUnmappedFields (Job $job)
    {
        $customerId = $this->getForm()->get('customer')->getData();

        if ($customerId)
        {
            $entityManager      = $this->getEntityManager();
            $contactPerson      = $this->getForm()->get(self::CONTACT_PERSON_DROPDOWN_PREFIX.$customerId)->getData();
            $customerRepository = $this->getCustomerRepository($entityManager);
            $customer           = $customerRepository->findById($customerId);

            if ($contactPerson) {
                $job->setContactPerson($contactPerson);
            }

            if ($customer) {
                $job->setCustomer($customer);
            }

            $entityManager->persist($job);
            $entityManager->flush($job);
        }
    }

    /**
     * @param mixed $object
     */
    public function postPersist($object)
    {
        $this->mapUnmappedFields($object);

        parent::postPersist($object);
    }

    /**
     * @param mixed $object
     */
    public function postUpdate($object)
    {
        $this->mapUnmappedFields($object);

        parent::postUpdate($object);
    }
}

不管怎样,我终于自己解决了这个问题。这个问题给我赢得了一枚风滚草徽章。但是,如果有人需要它,可以打我。嗨,你是如何解决这个问题的,thanks@TheGooooogle很高兴知道你是如何处理这个案子的。