Исключение AutowiringFailedException при переопределении регистрационной формы FOSUserBundle


( Использование Symfony 3 на сервере WampServer в Windows 10)

Я пытаюсь расширить пользовательскую форму FOSBundle в соответствии с инструкциями из https://knpuniversity.com/screencast/fosuserbundle/customize-forms (Я выбрал опцию "переопределить", поэтому я пропустил часть "расширить", используя 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;
    }

}

В сервисах.yml:

(...)
    app.form.registration:
        class: AppBundle\Form\RegistrationFormType
        tags:
            - { name: form.type }

В файле config.yml:

(...)
fos_user:
    (...)
    registration:
        form:
            type: AppBundle\Form\RegistrationFormType
Author: TTT, 2017-08-18

2 answers

Удалите свой __constructor из RegistrationFormType:

И измените свой data_class:

$resolver->setDefaults(array(
      ......
      'data_class' => 'AppBundle\Entity\User', //Your user Entity class
      ......
 1
Author: Imanali Mamadiev, 2017-08-18 10:07:49

Я понимаю, что уже есть принятый ответ, но он включает в себя рефакторинг класса типа формы и перемещение аргументов конструктора в массив параметров. Что может быть немного неприятно, так как это означает, что вам нужно установить значение параметра из любого места, где создается форма.

Основная проблема заключается в том, что autowire не может определить желаемое значение строкового параметра. Отсюда и сообщение об ошибке, касающееся $class.

К счастью, вы можете передать $класс из своего определение услуги.

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

Должно сработать. Обратите также внимание на несколько более сжатую версию указания тега.

Последнее замечание заключается в том, что autowire все еще может вычислять дополнительные аргументы конструктора объектов. Таким образом, приведенное выше определение службы также будет работать для:

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

Забавно поиграть, хотя у меня все еще есть некоторые опасения по поводу автоматического подключения в отношении долгосрочного обслуживания.

Еще одно уточнение. 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 команда. Или, может быть, Люциус Малфой.

 4
Author: Cerad, 2017-08-18 13:34:10