php - 覆盖 FOSUserBundle 注册表时出现 AutowiringFailedException

标签 php symfony fosuserbundle

(在 Windows 10 的 WampServer 上使用 Symfony 3)

我正在尝试根据 https://knpuniversity.com/screencast/fosuserbundle/customize-forms 中的以下说明扩展 FOSBundle 的用户表单。 (我选择了“覆盖”选项,因此我使用 getParent() 跳过了“扩展”部分)

我明白了

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

自定义用户类别

<?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

最佳答案

我意识到已经有一个可接受的答案,但它涉及重构表单类型类并将构造函数参数移至选项数组。这可能有点麻烦,因为这意味着您必须从创建表单的任何位置设置选项值。

基本问题是 Autowiring 不可能找出字符串参数的所需值。因此出现有关 $class 的错误消息。

幸运的是,您可以从服务定义中传递 $class。

// services.yml
AppBundle\Form\RegistrationFormType:
    tags: [form.type]
    arguments: {$class: 'AppBundle\Entity\User'}

应该可以解决问题。另请注意指定标签的稍微精简的版本。

最后一点是, Autowiring 仍然可以计算出额外的对象构造函数参数。因此上述服务定义也适用于:

class RegistrationFormType extends AbstractType
{
    public function __construct(LoggerInterface $logger, string $class)

玩起来很有趣,尽管我仍然对 Autowiring 在长期维护方面存在一些担忧。

还有一点细化。 Symfony 现在可以根据服务实现的内容自动连接标签。 https://symfony.com/doc/current/service_container/tags.html#autoconfiguring-tags因此任何实现 FormTypeInterface 的类都会自动标记为 form.type

服务定义现在可以简化为:

AppBundle\Form\RegistrationFormType:
    $class: 'AppBundle\Entity\User'

跟踪正在配置的所有内容可能具有挑战性。此命令可以帮助排除故障:

php bin/console debug:container "AppBundle\Form\RegistrationFormType"

我猜测哈利·波特是 Symfony 开发团队的 secret 成员。或者也许是卢修斯·马尔福。

关于php - 覆盖 FOSUserBundle 注册表时出现 AutowiringFailedException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45753063/

相关文章:

php - 在 Symfony2 中放置模型辅助函数的位置

forms - 如何按照实体之间的多对多关系将默认值设置为连接用户之后的 symfony 表单字段(用户字段)

symfony - 使用 FosUserBundle 创建管理员用户

php - 如何在包含冒号的php中获取单词(:)?

php - 在php中读取unicode文件

symfony - 如何在生产中调试 symfony 错误 "Untrusted Host"

php - FosUserBundle不将数据保存在mongodb数据库中

php - 拉拉维尔 5.4 : Converting a raw SQL query in Laravel Eloquent

php - 语法错误或访问冲突 : 1055 Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column

mysql - 如何通过 Symfony 4 连接到使用 MAMP 创建的 mySQL 数据库?