问题描述
我尝试从类别类型表单中设置字段"作者"的值.我希望它是使用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()
的数组正如我所看到的,您有几种解决此问题的方法
-
更新参数签名,并要求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() ) );
-
不要将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'; } }
-
甚至都不打扰将作者放在表单中,让控制器处理
$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()))); } }
-
将您的表单类型转换为服务,并用户用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)));
问题描述
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
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() ) );
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'; } }
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()))); } }
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)));