覆盖 FOSUserBundle 注册表时出现 AutowiringFailedException
AutowiringFailedException when overriding FOSUserBundle registration form
(在 Windows 10 上的 WampServer 上使用 Symfony 3)
我正在尝试根据 https://knpuniversity.com/screencast/fosuserbundle/customize-forms 中的说明扩展 FOSBundle 的用户表单
(我选择了 "override" 选项,所以我使用 getParent()
跳过了 "extend" 部分)
我明白了
**AutowiringFailedException**
Cannot autowire service "app.form.registration": argument "$class" of method "AppBundle\Form\RegistrationFormType::__construct()" must have a type-hint or be given a value explicitly.
部分配置:
..\Appbundle\Form\RegistrationFormType.php
<?php
/*
* This file is part of the FOSUserBundle package.
*
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace AppBundle\Form;
use FOS\UserBundle\Util\LegacyFormHelper;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class RegistrationFormType extends AbstractType
{
/**
* @var string
*/
private $class;
/**
* @param string $class The User class name
*/
public function __construct($class)
{
$this->class = $class;
}
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('email', LegacyFormHelper::getType('Symfony\Component\Form\Extension\Core\Type\EmailType'), array('label' => 'form.email', 'translation_domain' => 'FOSUserBundle'))
->add('username', null, array('label' => 'form.username', 'translation_domain' => 'FOSUserBundle'))
->add('plainPassword', LegacyFormHelper::getType('Symfony\Component\Form\Extension\Core\Type\RepeatedType'), array(
'type' => LegacyFormHelper::getType('Symfony\Component\Form\Extension\Core\Type\PasswordType'),
'options' => array('translation_domain' => 'FOSUserBundle'),
'first_options' => array('label' => 'form.password'),
'second_options' => array('label' => 'form.password_confirmation'),
'invalid_message' => 'fos_user.password.mismatch',
))
->add('number')
;
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => $this->class,
'csrf_token_id' => 'registration',
// BC for SF < 2.8
'intention' => 'registration',
));
}
// BC for SF < 3.0
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->getBlockPrefix();
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'fos_user_registration';
}
}
自定义用户class
<?php
namespace AppBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="`fasuser`")
*/
class FasUser extends BaseUser
{
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
*/
protected $id;
public function getId()
{
return $this->id;
}
/**
* @ORM\Column(type="string")
*/
protected $Number;
public function getNumber()
{
return $this->Number;
}
public function setNumber(string $number)
{
$this->Number = $number;
}
}
在services.yml中:
(...)
app.form.registration:
class: AppBundle\Form\RegistrationFormType
tags:
- { name: form.type }
在config.yml中:
(...)
fos_user:
(...)
registration:
form:
type: AppBundle\Form\RegistrationFormType
从 RegistrationFormType
中删除你的 __constructor
:
并更改您的 data_class
:
$resolver->setDefaults(array(
......
'data_class' => 'AppBundle\Entity\User', //Your user Entity class
......
我意识到已经有一个可接受的答案,但它涉及重构表单类型 class 并将构造函数参数移至选项数组。这可能有点麻烦,因为这意味着您必须从创建表单的任何地方设置选项值。
基本问题是自动装配不可能计算出字符串参数的所需值。因此出现有关 $class 的错误消息。
幸运的是,您可以从服务定义中传递 $class。
// services.yml
AppBundle\Form\RegistrationFormType:
tags: [form.type]
arguments: {$class: 'AppBundle\Entity\User'}
应该可以解决问题。另请注意指定标记的稍微更简洁的版本。
最后要注意的是,自动装配仍然可以计算出额外的对象构造函数参数。所以上面的服务定义也适用于:
class RegistrationFormType extends AbstractType
{
public function __construct(LoggerInterface $logger, string $class)
虽然我仍然对自动装配的长期维护有一些担忧,但玩起来很有趣。
再细化一点。 Symfony 现在可以根据服务实现的内容自动连接标签。 https://symfony.com/doc/current/service_container/tags.html#autoconfiguring-tags 所以任何实现 FormTypeInterface 的 class 都会被自动标记为 form.type
服务定义现在可以简化为:
AppBundle\Form\RegistrationFormType:
$class: 'AppBundle\Entity\User'
跟踪正在配置的所有内容可能具有挑战性。此命令可以帮助解决问题:
php bin/console debug:container "AppBundle\Form\RegistrationFormType"
我猜哈利波特是 Symfony 开发团队的秘密成员。或者也许是卢修斯·马尔福。
我的解决方案:覆盖父构造函数
namespace App\AppBundle\Form\Type\Admin;
use App\AppBundle\Entity\User;
use FOS\UserBundle\Form\Type\ChangePasswordFormType as BaseType;
class ChangePasswordFormType extends BaseType
{
/**
* @param string $class The User class name
*/
public function __construct(User $class)
{
parent::__construct($class);
}
public function getBlockPrefix()
{
return 'sonata_user_admin_change_password';
}
}
(在 Windows 10 上的 WampServer 上使用 Symfony 3)
我正在尝试根据 https://knpuniversity.com/screencast/fosuserbundle/customize-forms 中的说明扩展 FOSBundle 的用户表单
(我选择了 "override" 选项,所以我使用 getParent()
跳过了 "extend" 部分)
我明白了
**AutowiringFailedException**
Cannot autowire service "app.form.registration": argument "$class" of method "AppBundle\Form\RegistrationFormType::__construct()" must have a type-hint or be given a value explicitly.
部分配置: ..\Appbundle\Form\RegistrationFormType.php
<?php
/*
* This file is part of the FOSUserBundle package.
*
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace AppBundle\Form;
use FOS\UserBundle\Util\LegacyFormHelper;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class RegistrationFormType extends AbstractType
{
/**
* @var string
*/
private $class;
/**
* @param string $class The User class name
*/
public function __construct($class)
{
$this->class = $class;
}
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('email', LegacyFormHelper::getType('Symfony\Component\Form\Extension\Core\Type\EmailType'), array('label' => 'form.email', 'translation_domain' => 'FOSUserBundle'))
->add('username', null, array('label' => 'form.username', 'translation_domain' => 'FOSUserBundle'))
->add('plainPassword', LegacyFormHelper::getType('Symfony\Component\Form\Extension\Core\Type\RepeatedType'), array(
'type' => LegacyFormHelper::getType('Symfony\Component\Form\Extension\Core\Type\PasswordType'),
'options' => array('translation_domain' => 'FOSUserBundle'),
'first_options' => array('label' => 'form.password'),
'second_options' => array('label' => 'form.password_confirmation'),
'invalid_message' => 'fos_user.password.mismatch',
))
->add('number')
;
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => $this->class,
'csrf_token_id' => 'registration',
// BC for SF < 2.8
'intention' => 'registration',
));
}
// BC for SF < 3.0
/**
* {@inheritdoc}
*/
public function getName()
{
return $this->getBlockPrefix();
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'fos_user_registration';
}
}
自定义用户class
<?php
namespace AppBundle\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="`fasuser`")
*/
class FasUser extends BaseUser
{
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
*/
protected $id;
public function getId()
{
return $this->id;
}
/**
* @ORM\Column(type="string")
*/
protected $Number;
public function getNumber()
{
return $this->Number;
}
public function setNumber(string $number)
{
$this->Number = $number;
}
}
在services.yml中:
(...)
app.form.registration:
class: AppBundle\Form\RegistrationFormType
tags:
- { name: form.type }
在config.yml中:
(...)
fos_user:
(...)
registration:
form:
type: AppBundle\Form\RegistrationFormType
从 RegistrationFormType
中删除你的 __constructor
:
并更改您的 data_class
:
$resolver->setDefaults(array(
......
'data_class' => 'AppBundle\Entity\User', //Your user Entity class
......
我意识到已经有一个可接受的答案,但它涉及重构表单类型 class 并将构造函数参数移至选项数组。这可能有点麻烦,因为这意味着您必须从创建表单的任何地方设置选项值。
基本问题是自动装配不可能计算出字符串参数的所需值。因此出现有关 $class 的错误消息。
幸运的是,您可以从服务定义中传递 $class。
// services.yml
AppBundle\Form\RegistrationFormType:
tags: [form.type]
arguments: {$class: 'AppBundle\Entity\User'}
应该可以解决问题。另请注意指定标记的稍微更简洁的版本。
最后要注意的是,自动装配仍然可以计算出额外的对象构造函数参数。所以上面的服务定义也适用于:
class RegistrationFormType extends AbstractType
{
public function __construct(LoggerInterface $logger, string $class)
虽然我仍然对自动装配的长期维护有一些担忧,但玩起来很有趣。
再细化一点。 Symfony 现在可以根据服务实现的内容自动连接标签。 https://symfony.com/doc/current/service_container/tags.html#autoconfiguring-tags 所以任何实现 FormTypeInterface 的 class 都会被自动标记为 form.type
服务定义现在可以简化为:
AppBundle\Form\RegistrationFormType:
$class: 'AppBundle\Entity\User'
跟踪正在配置的所有内容可能具有挑战性。此命令可以帮助解决问题:
php bin/console debug:container "AppBundle\Form\RegistrationFormType"
我猜哈利波特是 Symfony 开发团队的秘密成员。或者也许是卢修斯·马尔福。
我的解决方案:覆盖父构造函数
namespace App\AppBundle\Form\Type\Admin;
use App\AppBundle\Entity\User;
use FOS\UserBundle\Form\Type\ChangePasswordFormType as BaseType;
class ChangePasswordFormType extends BaseType
{
/**
* @param string $class The User class name
*/
public function __construct(User $class)
{
parent::__construct($class);
}
public function getBlockPrefix()
{
return 'sonata_user_admin_change_password';
}
}