Symfony FormType содержит 1 абстрактный метод после обновления до 2.8.

Я только что обновился до 2.8, и теперь я получаю следующую ошибку при вызове функции создания фабрики форм.

Error: Class Symfony\Component\Form\Extension\Core\Type\FormType contains 1 
abstract method and must therefore be declared abstract or implement the 
remaining methods (Symfony\Component\Form\FormTypeInterface::setDefaultOptions)

Вызов FormFactory выглядит так:

$this->formFactory->create(
        get_class(new ProductType()),
        $product,
        [
            'method' => 'POST',
            'type' => $type,
            'locales' => $context->shop->getLocales(),
            'product' => $product,
            'numberDataTransformer' => $this->numberTransformerFactory->createFromLocale(
                $context->user->getLocale(),
                $context->shop->getDefaultLocale()
            ),
            'priceType' => $context->shop->getConfiguration()->getProductConfiguration()->getPricesBackend(),
            'isShortDescriptionEnabled' => $context->shop->getConfiguration()->getProductConfiguration()->isShortDescriptionEnabled()
        ]);

Я попробовал несколько способов передать ProductType функции, но ни один из них не работает. Я всегда получаю один из двух результатов: либо результат заключается в том, что тип не может быть найден, либо возвращается ошибка, что FormType не реализует setDefaultOptions.

Что я упустил?

РЕДАКТИРОВАТЬ:

Вот дополнительный код:

Объявление параметра formFactory:

public function __construct(Request $request, FormFactoryInterface $formFactory)
{
    $this->request = $request;
    $this->formFactory = $formFactory;
}

Класс ProductType

<?php

namespace CustomNamespace\BackendBundle\Product\Form;

use CustomNamespace\BackendBundle\Common\NumberDataTransformer;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use CustomNamespace\BackendBundle\Product\Form\ImageType;
use ShopwareEasy\BackendBundle\Product\Form\AttachmentType;
use Symfony\Component\Validator\Exception\InvalidOptionsException;

/**
 * Form element type for products.
 */
class ProductType extends AbstractType
{
    /**
     * @var string
     */
    private $method;

    /**
     * @var string
     */
    private $type;

    /**
     * @var array
     */
    private $locales;

    /**
     * @var Product
     */
    private $product;

    /**
     * @var \CustomNamespace\BackendBundle\Common\NumberDataTransformer
     */
    private $numberDataTransformer;

    /**
     * @var string
     */
    private $priceType;

    /**
     * @var bool
     */
    private $isShortDescriptionEnabled;

    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     * @return void
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        parent::buildForm($builder, $options);

        $builder->setMethod($this->method);
        $regionType = new RegionShippingTimeType();

        if ($this->type == 'download') {
            $regionType->enableForDownloadableProduct();
        }

        $builder->add('regions', 'collection', array(
            'type'   => $regionType,
            'label' => false,
            'options'  => array(
                'required'  => false,
                'attr'      => array('class' => 'email-box')
            ),
        ));

        $builder->add('vendor', 'text', ['label' => 'form_product_vendor']);
        if ($this->type == 'normal') {
            $builder->add(
                'mainVariant',
                new MainVariantNormalType(
                    $this->method,
                    $this->locales,
                    $this->product,
                    $this->numberDataTransformer,
                    $this->priceType,
                    $this->isShortDescriptionEnabled
                ),
                ['error_bubbling' => false, 'label' => false]
            );
        } elseif ($this->type == 'download') {
            $builder->add(
                'mainVariant',
                new MainVariantDownloadType(
                    $this->method,
                    $this->locales,
                    $this->product,
                    $this->numberDataTransformer,
                    $this->priceType,
                    $this->isShortDescriptionEnabled
                ),
                ['error_bubbling' => false, 'label' => false]
            );
        } elseif ($this->type == 'variant') {
            $builder->add(
                'mainVariant',
                new MainVariantVariantType(
                    $this->method,
                    $this->locales,
                    $this->product,
                    $this->numberDataTransformer,
                    $this->priceType,
                    $this->isShortDescriptionEnabled
                ),
                ['error_bubbling' => false, 'label' => false]
            );
        }

        if ($this->method == 'PUT') {
            $builder->add(
                'images',
                new ImageType(),
                ['error_bubbling' => true, 'label' => false]
            );

            $builder->add(
                'attachments',
                new AttachmentType(),
                ['error_bubbling' => true, 'label' => false]
            );
        }
    }

    /**
     * @param \Symfony\Component\OptionsResolver\OptionsResolverInterface $resolver
     */
    public function configureOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(
            array(
                'data_class' => 'CustomNamespace\\BackendBundle\\Product\\Product',
                'csrf_protection' => false,
                'error_bubbling' => false,
                'cascade_validation' => true,
                'method' => 'POST',
                'type' => 'normal'
            )
        );

        parent::configureOptions($resolver);
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver) {
        /** @var OptionResolver $resolver */
        $this->configureOptions($resolver);
    }

    public function getName() {
        return get_class($this);
    }
}

person SvenFinke    schedule 15.12.2015    source источник
comment
Предоставьте нам больше кода.   -  person Michael Sivolobov    schedule 15.12.2015
comment
@MichaelSivolobov Что еще тебе нужно? Это единственное важное место. Думаю, нет необходимости публиковать здесь код Symfony 2.8 ;)   -  person SvenFinke    schedule 15.12.2015
comment
Разместите здесь свой код ProductType. Что у тебя в $this->formFactory? Где вы его загрузили?   -  person Michael Sivolobov    schedule 15.12.2015
comment
@MichaelSivolobov Я добавил класс ProductType. Фабрика является реализацией FormFactoryInterface, дамп FQCN показывает мне, что это стандарт Symfonies FormFactory   -  person SvenFinke    schedule 15.12.2015
comment
Почему вы не хотите использовать обычные имена? Зачем вам этот стиль, похожий на Symfony3? Сделайте типичное имя product и используйте его.   -  person Michael Sivolobov    schedule 15.12.2015
comment
Возвращает ли get_class(new ProductType()) ожидаемый fqcn? Сообщение об ошибке жалуется на FormType, а не на ProductType. Попробуйте заменить его фактической строкой согласно примеру в книге или ProductType::class   -  person Cerad    schedule 15.12.2015
comment
также вам не нужно использовать setDefaultOptions при реализации configureOptions   -  person Michael Sivolobov    schedule 15.12.2015
comment
@Cerad Возвращает правильный FQCN. Проблема в том, что в процессе создания Builder symfony пытается создать FormType, потому что он является родителем AbstractType, но FormType не может быть создан, потому что один абстрактный метод не реализован. Что меня интересует: как это может происходить только в моем случае? Я понимаю, почему возникает эта ошибка, и этот код находится в репозитории git. Но я думаю, что гораздо больше людей будут жаловаться на это, если это общая проблема...   -  person SvenFinke    schedule 15.12.2015
comment
@MichaelSivolobov Я реализовал это для Британской Колумбии. Если какой-то старый компонент попытается вызвать setDefaultOptions, это все еще возможно.   -  person SvenFinke    schedule 15.12.2015
comment
Это не общая проблема. Ваша ошибка связана с FormType, а не с ProductType, и поэтому она возникает. Вам нужно перейти на обычное имя вашей фабрики. Почему вы не хотите использовать обычные имена? И насчет BC: если у вас уже есть Symfony 2.8 и ваш ProductType реализует новый интерфейс, он всегда будет зависеть от Symfony 2.8. Таким образом, любой старый компонент, который использует вашу форму, делает это через компонент Symfony Forms версии 2.8, поэтому ваш метод BC никогда не будет использоваться.   -  person Michael Sivolobov    schedule 15.12.2015
comment
Попробуйте удалить метод getName() из типа формы. Вам это больше не нужно. Кроме того, создание экземпляра объекта для получения пространства имен класса действительно странно и расточительно. Я бы просто использовал ProductType::class.   -  person Jakub Zalas    schedule 15.12.2015
comment
какой код для Symfony\Component\Form\AbstractType?   -  person Max P.    schedule 15.12.2015
comment
FormType расширяет BaseType, который, в свою очередь, расширяет AbstractType. Таким образом, FormType вообще не является родителем ProductType. Что-то в вашем коде заставляет его пытаться создать FormType вместо ProductType. Это все очень странно. Возможно, попробуйте очистить все кеши и даже удалить каталог поставщика и выполнить полную переустановку. Черт, даже перезагрузка, чтобы убедиться, что APC не связывается с вами.   -  person Cerad    schedule 15.12.2015
comment
Я думаю, что проблема может заключаться в том, что все остальные типы создаются внутри ProductType с использованием старого стиля 2.7. У вас также есть много других вещей внутри ProductType. Попробуйте все закомментировать и посмотреть, что получится.   -  person Cerad    schedule 15.12.2015
comment
@Cerad FormType не является родителем ProductType, но использует его. Иерархия типов определяется методом getParent(), а не только иерархией классов.   -  person Max P.    schedule 15.12.2015
comment
Не вижу getParent в вашем опубликованном коде. В любом случае, у вас там слишком много вещей, чтобы я мог видеть, что происходит. Удачи.   -  person Cerad    schedule 15.12.2015
comment
Удалите setDefaultOptions(), замените configureOptions(OptionsResolverInterface $resolver) на public function configureOptions(OptionsResolver $resolver) и избавьтесь от вызова parent::configureOptions($resolver);   -  person Jason Roman    schedule 17.12.2015


Ответы (1)


Проблема была вызвана файлами, которые вообще не обновлялись. Реализация setDefaultOptions все еще должна существовать в классах Symfony 2.8, но ее не было. После уничтожения моего бродяги и воссоздания его снова все заработало нормально.

Но спасибо всем за помощь!

person SvenFinke    schedule 22.12.2015