Symfony/FOS-将用户ID变量传递给一个表单 类型[英] Symfony/FOS - pass the user id variable to a form Type

本文是小编为大家收集整理的关于Symfony/FOS-将用户ID变量传递给一个表单 类型的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我尝试从类别类型表单中设置字段"作者"的值.我希望它是使用FOS捆绑包登录的当前用户的用户ID.

我的类别类型表格:

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(),
        ));
}

我在运行动作时捕获此错误:

可追踪致命错误:参数1传递给我的\ categorybundle \ form \ categoryType :: __ construct()必须是一个数组,无给定,in/my/categorybundle/controller/categorycontroller.php in 55 in 55 in/conter/categorybundle/categorybundle/categorycontroller.php my/categorybundle/form/categoryType.php行13

我已经传递给表格的数组了吗?

推荐答案

您的问题在此行

$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 array My\CategoryBundle\Form\CategoryType::buildForm()

的数组

正如我所看到的,您有几种解决此问题的方法

  1. 更新参数签名,并要求My\CategoryBundle\FormCategoryType::__construct()通过/接收整个用户对象(不仅仅是他们的ID-请记住,您正在使用学说关系,而不是低级的外国键它们映射到)

    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');
    

其他推荐答案

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

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

应该是

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

本文地址:https://www.itbaoku.cn/post/2090812.html

问题描述

I try to set the value of a field "author" from a CategoryType form. I want it to be the user id from the current user logged in with FOS bundle.

my CategoryType form :

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';
    }
}

And my controller Action :

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(),
        ));
}

I catch this error while running the action :

Catchable Fatal Error: Argument 1 passed to My\CategoryBundle\Form\CategoryType::__construct() must be an array, none given, called in /My/CategoryBundle/Controller/CategoryController.php on line 55 and defined in /My/CategoryBundle/Form/CategoryType.php line 13

Isn't it already an array that I am passing to the form ?

推荐答案

Your problem is on this line

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

You're not satisfying the contract for My\CategoryBundle\FormCategoryType::__construct(). Here, let's look at it another way.

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

The array that you send as the 2nd argument to Symfony\Component\Form\FormFactory::create() is what is ultimately injected as $options array My\CategoryBundle\Form\CategoryType::buildForm()

As I see it, you have a few different ways to resolve this

  1. Update the argument signature AND call for My\CategoryBundle\FormCategoryType::__construct() to pass/receive the entire user object (not just their id - remember that you're working with Doctrine relationships at this point, not the lower-level foreign keys that they map to)

    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;
        }
    

    and

    $form = $this->get('form.factory')->create(
        new CategoryType(
          $this->get('security.context')->getToken()->getUser()
        )
    );
    
  2. Don't inject the User into the type's constructor, just let the options handle it

    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. Not even bother putting the author in the form and let the controller handle it

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

    and

    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. Turn your form type into a service and user the DI Container to inject the security context

    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%"]
    

    Update your type to receive the 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();
        }
    

    Then in your controller, create the form with its service name

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

其他推荐答案

Your current code passes the array to the create() method, not your CategoryType construct.

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

should be

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