【问题标题】:Symfony 3.2 Form events : Can't retrieve dataSymfony 3.2 表单事件:无法检索数据
【发布时间】:2018-01-17 09:22:59
【问题描述】:

我没有找到任何与我的问题相关的主题,而且我的情况非常特殊,这就是我寻求帮助的原因。

我有 4 个相关实体:PurchaseOrder、SapPO、项目和产品。如下所示,PurchaseOrder 和 SapPo 之间是一对多关联,SapPo 和 Project 之间是一对多双向关联,purchaseOrder 和产品之间是多对多关联。

PurchaseOder.php:

/**
 * @ORM\ManyToMany(targetEntity="SapPo",cascade={"persist","remove"})
 * @ORM\JoinTable(name="po_sappo",
 *      joinColumns={@ORM\JoinColumn(name="po_id", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM\JoinColumn(name="sappo_id", referencedColumnName="id", unique=true,onDelete="CASCADE")}
 *      )
 */
private $sapPo;

/**
 * @ORM\ManyToMany(targetEntity="Product", mappedBy="purchaseOrders")
 */
private $products;

SapPo.php

/**
 * @ORM\ManyToOne(targetEntity="Project", inversedBy="sapPos")
 * @ORM\JoinColumn(name="project_sap", referencedColumnName="id")
 */
private $project ;

项目.php:

/**
 * @ORM\OneToMany(targetEntity="SapPo", mappedBy="project")
 */
private $sapPos ;

/**
 * @ORM\ManyToMany(targetEntity="Product", inversedBy="projet")
 * @ORM\JoinTable(name="product_project")
 */
private $products;

最后是 Product.php:

/**
 * @ORM\ManyToMany(targetEntity="PurchaseOrder", inversedBy="products", 
  cascade={"persist"})
 * @ORM\JoinTable(name="purchaseOrders_products")
 */
private $purchaseOrders;

/**
 * @ORM\ManyToMany(targetEntity="Project", mappedBy="products")
 */
private $projet;

我想要做的是用代表所选项目数据之间交集的产品填充表单。 例如,我们必须选择项目 "Project 1",它有两个产品 "product 1""product 2" 和另一个项目 "project 2" 有两个产品 "product 2""product 3"

在此示例中,“product 2” 是交集,需要用它填充表单。

使用下面显示的代码并使用 FormEvents,我已经成功地使用必要的 AJAX 调用和之后的 ArrayCollection 过滤器填充了必要的数据。问题是,一旦我提交表单,我就没有选择产品,但我得到一个空的 ArrayCollection。

PurchaseOrderType.php:

        /**
     * Product modifier used to modify products after the SAP PO choice validation
     * @param FormInterface $form
     * @param $sapPos
     */

    $productModifier = function (FormInterface $form, $names){


        $form->add('products', EntityType::class,array(
            'class' => 'FollowupBundle:Product',
            'multiple' => true,
            'expanded' => false,
            'query_builder' => function(EntityRepository $er) use ($names) {
                $qb = $er->createQueryBuilder('u') ;
                $qb->where("u.name IN (:projects)")
                    ->setParameter('projects',$names) ;
                return $qb ;
            },
            'choice_label' => 'name',
            'placeholder' => 'Selectionner le produit'
        ));
    };



    $builder->addEventListener(
        FormEvents::PRE_SET_DATA,
        function (FormEvent $event) {
            $form = $event->getForm();
            $data = $event->getData();
            $sapPos = $data->getSapPo();



            $form->add('products',EntityType::class,array(
                'class' => 'FollowupBundle:Product',
                'multiple' => true,
                'expanded' => false,
                'required' => false,
                'choices' => [],
                'placeholder' => 'selectionner les produits',
                'choice_label' => 'name'


            )) ;

        }) ;



    $builder->get('sapPo')->addEventListener(
        FormEvents::POST_SUBMIT,
        function (FormEvent $event) use ($productModifier){
            $sapPos = $event->getForm()->getData() ;
            $namesList = $this->getNamesFromSapPo($sapPos) ;

            $productModifier($event->getForm()->getParent(), $namesList);
        },900
    ) ;

编辑

这是用于过滤和提取要在查询生成器中使用的产品名称的函数。

 /**
 * @param Product $product
 * @param ArrayCollection $sapPos
 * @return bool
 */
public function filterProducts(Product $product, $sapPos){
    $isCommon = true ;
    foreach ($sapPos as $sapPo){
        if (!$sapPo->getProject()->getProducts()->contains($product)){
            $isCommon = false;
        }else {
        }
    }
    return $isCommon;
}



public function getNamesFromSapPo($sapPos){
    $primilnaryProducts  = new ArrayCollection() ;
    $lastProducts = new ArrayCollection() ;
    $namesList = [] ;
    foreach ($sapPos as $sapPo){
        foreach ($sapPo->getProject()->getProducts() as $product){
            $primilnaryProducts->add($product) ;
        }
    }
    // filter products

    $lastProducts = $primilnaryProducts->filter(
        function ($entry) use ($sapPos){
            return $this->filterProducts($entry,$sapPos) ;
        }
    ) ;

    //get Names

    foreach ($lastProducts as $product){
        $namesList[] = $product->getName() ;
    }


    return $namesList ;



}

欢迎任何提示或技术建议!谢谢。

【问题讨论】:

  • 正如我从https://symfony.com/doc/current/reference/forms/types/entity.html#choices 看到的(我记得):您的'choices' => [] 将覆盖字段中的任何数据
  • 谢谢!问题是我忘记在 POST_SUBMIT 函数中使用表单修饰符了。
  • 太棒了。你找到了解决方案。顺便说一句,在处理表单事件时进行更多调试 - 是找出所有问题的最佳方法,当然,如果您不经常编写它们。
  • 我通常使用 PSR/Logger,但遗憾的是我无法像在 Java 中那样记录对象。
  • 您可以在记录对象之前尝试对其进行序列化。而且,imo,日志记录并不是最好的调试方式 - 尝试使用 xdebug,它会更好。

标签: php forms symfony symfony-3.2


【解决方案1】:

我忘记在 POST_SUBMIT 函数中使用表单修饰符,我不得不从表单构建器中删除 'choices' => [] 来覆盖发送到服务器的数据。

【讨论】:

    猜你喜欢
    • 2023-04-01
    • 1970-01-01
    • 2015-02-09
    • 2020-02-06
    • 1970-01-01
    • 2014-09-10
    • 1970-01-01
    • 1970-01-01
    • 2018-02-21
    相关资源
    最近更新 更多