Symfony 3.4表单中的CollectionType数组

时间:2018-04-25 16:42:52

标签: php forms symfony collections symfony-forms

我已经获得了实体的数组Cart,我想生成一般形式,就像在屏幕上一样。

enter image description here

如您所见,我希望每行中都有可编辑的字段数量,表示Cart实体,我希望能够一次更新所有这些字段。

class Cart
{
/**
 * @ORM\Id
 * @ORM\Column(type="integer")
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @ORM\ManyToOne(targetEntity="User", inversedBy="carts")
 */
private $userId;

/**
 * @ORM\ManyToOne(targetEntity="Product", inversedBy="carts")
 */
protected $product;

/**
 * @ORM\Column(type="integer")
 */
private $quantity;

/*gettes & setters */
}

现在,我有一个想要接收CollectionType的表单来处理它,但是 - 我只有一个实体数组,所以它正在转储LogicalException。

我需要做什么 - 有什么方法可以将数组解析为CollectionType,或者我可以用另一种方式从数据库中获取一组购物车实体?:

$carts=$this->getDoctrine()->getRepository(Cart::class)->findByUserId($user);

1 个答案:

答案 0 :(得分:1)

有一个例子说明如何在Symfony Documentation on How to Embed a Collection of Forms中完成您想要达到的目标。

对于您的特定用例,您需要创建UserCartsForm和单独的CartsForm

UserCart中,将carts字段添加为CollectionType。 然后,Symfony将以一系列形式处理该字段。

的src /的appbundle /窗体/ UserCart.php

namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type as FormType;

class UserCartsForm extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
         $builder->add('carts', FormType\CollectionType::class, [
             'label' => false,
             'entry_type' => CartsForm::class,
             'entry_options' => array('label' => false),
         ]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => User::class,
        ]);
    }
}

将您希望在表单上编辑的字段添加到CartsForm

的src /的appbundle /窗体/ CartsForm.php

namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type as FormType;

class CartsForm extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
         $builder->add('quantity', FormType\IntegerType::class, [
           'label' => false
            //...
         ]);
         //...
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Cart::class,
        ]);
    }
}

在您的控制器中,将用户实体引用为UserCartsForm数据。

的src /的appbundle /控制器/ DefaultController.php

namespace AppBundle\Controller;

use AppBundle\Form\UserCartsForm;

class DefaultController extends Controller
{

   /**
    * @Route('/{id}/user-carts')
    */
   public function userCartsAction(Request $request, User $user)
   {
      $form = $this->createForm(UserCartsForm::class, $user);
      $form->handleRequest($request);
      if($form->isSubmitted() && $form->isValid())
      {
         //... process entity
         //$this->getDoctrine()->getManager()->flush($carts);
         return $this->redirectToRoute('some_route');
      }

      return $this->render('user_carts_form.html.twig', [
          'form' => $form
      ]);
   }
}

然后,您应该能够轻松地从枝条模板中检索数据,以便根据需要进行渲染。

应用程序/资源/视图/ user_carts_form.html.twig

{% form_start(form) %}
   <table>
   <thead>
   <tr>
       <td>Name</td>
       <td>Quantity</td>
       <td></td>
   </tr>
   </thead>
   <tbody>
   {% for cart in form.carts %}
   {% set cartEntity = cart.vars.data %}
   <tr>
       <td>{{ cartEntity.product.name }}</td>
       <td>{{ form_widget(cart.quantity) }}</td>
       <td><a class="button" href="{{ path('remove_cart_action', { id: cartEntity.id }) }}">Delete <icon/></a></td>
   <tr>
   {% endfor %}
   </tbody>
   </table>
   <button type="submit">Submit</button>
{% form_end(form) %}

实体约束更新

默认情况下,Symfony将在验证表单时使用分配给实体的所有约束(Default),导致$form->isValid()返回false。

  

https://symfony.com/doc/3.4/validation/groups.html

     

如果未指定任何组,则属于该组的所有约束   Default将被应用。

要解决此问题,请使用Validation Groups分隔实体约束并在各自的表单上声明所需的组。

示例:

的src /的appbundle /实体/ user.php的

namespace AppBundle\Entity;

use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Entity
 */
class User
{

    /**
     * @Assert\NotBlank(groups={"registration"})
     */
    private $username;

    //...
}

然后在所需表单use your validation group(s)RegistrationForm,在{0}}中,AbstractTye::configureOptionsOptionsResolver:$defaults中的所需群组声明为namespace AppBundle\Form; use Symfony\Component\Form\AbstractType; class RegistrationForm extends AbstractType { //... public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ 'data_class' => User::class, 'validation_groups' => ['registration'] ]); } }

的src /的appbundle /窗体/ RegistrationForm.php

User::NotBlank

现在,RegistrationForm::isValid()约束仅适用于UTF8或声明注册验证组的任何其他表单。