【问题标题】:Symfony/FOS - pass the user id variable to a form TypeSymfony/FOS - 将用户 id 变量传递给表单类型
【发布时间】:2013-11-06 13:34:39
【问题描述】:

我尝试从 CategoryType 表单中设置字段“作者”的值。我希望它是使用 FOS 包登录的当前用户的用户 ID。

我的 CategoryType 表单:

namespace My\CategoryBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class CategoryType extends AbstractType
{
    private $userId;

    public function __construct(array $userId)
    {
        $this->userId = $userId;
    }

     /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('title')
            ->add('author')
            ->add('content')
        ;
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'My\CategoryBundle\Entity\Category',
            'auteur' => $this->userId
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'my_categorybundle_category';
    }
}

还有我的控制器动作:

public function addAction()
{
    $category = new Category;
    $user = $this->get('security.context')->getToken()->getUser(); 
    $userId = $user->getId();

    $form = $this->get('form.factory')->create(new CategoryType(), array( 'author' => $userId));

    $request = $this->get('request');
    if ($request->getMethod() == 'POST') {
        $form->bind($request);

        if ($form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($category);
            $em->flush();

        return $this->redirect($this->generateUrl('mycategory_voir',
            array('id' => $category->getId())));
        }
    }
    return $this->render('MyCategoryBundle:Category:add.html.twig',
        array(
            'form' => $form->createView(),
        ));
}

我在运行操作时发现了这个错误:

可捕获的致命错误:传递给 My\CategoryBundle\Form\CategoryType::__construct() 的参数 1 必须是一个数组,没有给出,在第 55 行的 /My/CategoryBundle/Controller/CategoryController.php 中调用并在 / 中定义My/CategoryBundle/Form/CategoryType.php 第 13 行

我传递给表单的不是已经是一个数组了吗?

【问题讨论】:

    标签: symfony fosuserbundle formbuilder


    【解决方案1】:

    你的问题出在这一行

    $form = $this->get('form.factory')->create(new CategoryType(), array( 'author' => $userId));
    

    您不满足My\CategoryBundle\FormCategoryType::__construct() 的合同。在这里,让我们换个角度来看。

    $form = $this->get('form.factory')->create(
        new CategoryType(/* You told PHP to expect an array here */)
      , array('author' => $userId)
    );
    

    您作为第二个参数发送给Symfony\Component\Form\FormFactory::create() 的数组最终被注入为$options 数组My\CategoryBundle\Form\CategoryType::buildForm()

    在我看来,你有几种不同的方法来解决这个问题

    1. 更新参数签名并调用 My\CategoryBundle\FormCategoryType::__construct() 来传递/接收整个用户对象(不仅仅是他们的 id - 请记住,此时您正在处理 Doctrine 关系,而不是他们映射的较低级别的外键到)

      namespace My\CategoryBundle\Form;
      
      use My\CategoryBundle\Entity\User; /* Or whatver your User class is */
      use Symfony\Component\Form\AbstractType;
      use Symfony\Component\Form\FormBuilderInterface;
      use Symfony\Component\OptionsResolver\OptionsResolverInterface;
      
      class CategoryType extends AbstractType
      {
          private $author;
      
          public function __construct( User $author )
          {
              $this->author = $author;
          }
      

      $form = $this->get('form.factory')->create(
          new CategoryType(
            $this->get('security.context')->getToken()->getUser()
          )
      );
      
    2. 不要将User 注入到类型的构造函数中,让选项来处理它

      namespace My\CategoryBundle\Form;
      
      use Symfony\Component\Form\AbstractType;
      use Symfony\Component\Form\FormBuilderInterface;
      use Symfony\Component\OptionsResolver\OptionsResolverInterface;
      
      class CategoryType extends AbstractType
      {
          private $userId;
      
           /**
           * @param FormBuilderInterface $builder
           * @param array $options
           */
          public function buildForm(FormBuilderInterface $builder, array $options)
          {
              $builder
                  ->add('title')
                  ->add('author', 'hidden', array('data'=>$options['author']))
                  ->add('content')
              ;
          }
      
          /**
           * @param OptionsResolverInterface $resolver
           */
          public function setDefaultOptions(OptionsResolverInterface $resolver)
          {
              $resolver->setDefaults(array(
                  'data_class' => 'My\CategoryBundle\Entity\Category'
              ));
          }
      
          /**
           * @return string
           */
          public function getName()
          {
              return 'my_categorybundle_category';
          }
      }
      
    3. 甚至懒得把作者放在表单中,让控制器处理它

      $form = $this->get('form.factory')->create(
          new CategoryType()
        , array('author' => $this->get('security.context')->getToken()->getUser() )
      );
      

      if ($request->getMethod() == 'POST') {
          $form->bind($request);
      
          if ($form->isValid()) {
              $category->setAuthor(
                $this->get('security.context')->getToken()->getUser()
              );
              $em = $this->getDoctrine()->getManager();
              $em->persist($category);
              $em->flush();
      
          return $this->redirect($this->generateUrl('mycategory_voir',
              array('id' => $category->getId())));
          }
      }
      
    4. 将您的表单类型转换为服务并使用 DI 容器注入安全上下文

      app/config/config.yml

      services:
        form.type.my_categorybundle_category:
          class: My\CategoryBundle\Form\CategoryType
          tags:
            - {name: form.type, alias: my_categorybundle_category}
          arguments: ["%security.context%"]
      

      更新您的类型以接收安全上下文

      namespace My\CategoryBundle\Form;
      
      use Symfony\Component\Security\Core\SecurityContext;
      use Symfony\Component\Form\AbstractType;
      use Symfony\Component\Form\FormBuilderInterface;
      use Symfony\Component\OptionsResolver\OptionsResolverInterface;
      
      class CategoryType extends AbstractType
      {
          private $author;
      
          public function __construct( SecurityContext $security )
          {
              $this->author = $security->getToken()->getUser();
          }
      

      然后在您的控制器中,使用其服务名称创建表单

      $form = $this->get('form.factory')->create('my_categorybundle_category');
      

    【讨论】:

      【解决方案2】:

      您当前的代码将数组传递给 create() 方法,而不是您的 CategoryType 构造。

      $form = $this->get('form.factory')->create(new CategoryType(), array( 'author' => $userId));
      

      应该是

      $form = $this->get('form.factory')->create(new CategoryType(array( 'author' => $userId)));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-01-09
        • 1970-01-01
        • 1970-01-01
        • 2017-04-15
        • 1970-01-01
        • 1970-01-01
        • 2019-11-08
        • 1970-01-01
        相关资源
        最近更新 更多