Как Symfony 2 находит пользовательские типы форм? - PullRequest
0 голосов
/ 11 декабря 2011

Я читал Преобразования данных Я немного изменил его в своем коде. Я получаю

Не удалось загрузить тип "csv2tags"

У меня есть пользовательский тип формы

class CSV2TagsType extends AbstractType {
    public function buildForm(FormBuilder $builder, array $opts) {
        $builder->appendClientTransformer(new CSV2TagsTransformer());
    }
    public function getParent() {
        return 'text';
    }
    public function getName() {
        return 'csv2tags';
    }
}

Использование трансформатора:

class CSV2TagsTransformer implements DataTransformerInterface {
    /**
     * @var EntityManager
     */
    protected $em;
    public function __construct(EntityManager $em) {
        $this->em = $em;
    }
    // ... 
}

В services.yml

services:
    jm.blog.csv2tagsTransformer:
        class: JM\BlogBundle\Form\DataTransformer\CSV2TagsTransformer
        arguments: ["@doctrine.orm.entity_manager"]

Несколько вопросов:

  • Я переместил EntityManager в преобразователь вместо типа формы, это нормально?
  • Я не объявлял псевдоним для службы преобразования, как в документации. Я думал, что псевдоним для типа формы был из функции AbstractType::getName()? Нужно ли мне объявлять мой пользовательский тип формы как службу
  • Я переместил EntityManager на трансформатор. Правильно ли я поступил, когда сделал new CSV2TagsTransformer() без EntityManager?

Ответы [ 2 ]

3 голосов
/ 11 декабря 2011

Я просто дополню ответ, заданный @ greg0ire, который почти прав.

Во-первых, определенная вами служба должна быть вашим типом формы (CSV2TagsType), а не вашим преобразователем (CSV2TagsTransformer), потому что это тип формы, который используется конструктором форм. Поскольку построитель форм ожидает AbstractType, он не будет работать с вашим определением службы, поскольку преобразователь данных не является AbstractType. Как сказал @ greg0ire, вы должны пометить свой пользовательский тип формы тегом form.type.

services:
  jm.blog.csv2tagsType:
    class: JM\BlogBundle\Form\Type\CSV2TagsType
    arguments: ["@doctrine.orm.entity_manager"]
    tags:
      - { name: form.type, alias: csv2tags }

Значение, возвращаемое функцией getName в типе пользовательской формы, должно соответствовать указанному вами псевдониму (cvs2tags) или идентификатору службы, который вы указали (jm.blog.csv2tagsType). Именно так Symfony может найти ваш пользовательский тип. Он пытается найти идентификатор службы, заданный методом getName().

Для вас, преобразователь данных, есть небольшая проблема. Вы делаете new CSV2TagsTransformer(), но вы не передаете менеджер сущностей. Это приведет к ошибке. Вы не можете сделать это таким образом, потому что нет способа внедрить преобразователь данных сервисным способом.

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

class CSV2TagsType extends AbstractType 
{
    protected $em;

    public function __construct(EntityManager $em) {
        $this->em = $em;
    }

    public function buildForm(FormBuilder $builder, array $opts) {
        $builder->appendClientTransformer(new CSV2TagsTransformer($this->em));
    }

    // Rest of class
}

Таким образом, вы вводите менеджер сущностей в свой тип формы, что возможно, потому что тип формы определен как сервис. И в типе формы вы создаете экземпляр преобразователя данных и передаете в конструкцию менеджер сущностей, который был внедрен в тип формы.

Другим способом было бы объявить вас преобразователем данных как сервис, а затем внедрить его в тип формы. Таким образом, вы не создаете экземпляр преобразователя данных самостоятельно, а используете тот, который вставлен в конструктор типа формы. Итак, если вам не нужен менеджер сущностей в типе формы, вы можете пропустить его. Вот пример этой альтернативы:

services:
  jm.blog.csv2tagsTransformer:
    class: JM\BlogBundle\Form\DataTransformer\CSV2TagsTransformer
    arguments: ["@doctrine.orm.entity_manager"]

  jm.blog.csv2tagsType:
    class: JM\BlogBundle\Form\Type\CSV2TagsType
    arguments: ["@jm.blog.csv2tagsTransformer"]
    tags:
      - { name: form.type, alias: csv2tags }

class CSV2TagsType extends AbstractType 
{
    protected $transformer;

    public function __construct(CSV2TagsTransformer $transformer) {
        $this->transformer= $transformer;
    }

    public function buildForm(FormBuilder $builder, array $opts) {
        $builder->appendClientTransformer($this->transformer);
    }

    // Rest of class
}

Вот небольшое резюме ответов на ваш вопрос:

  1. Это правильно.
  2. Псевдоним не требуется для службы преобразования. Но, как сказал @ greg0ire, вам нужно определить сервис для вашего типа формы. Функция getName() должна возвращать идентификатор, который следует использовать. Это может быть определенный псевдоним или идентификатор службы напрямую. Обычно люди используют псевдоним в качестве значения, возвращаемого getName.
  3. Неправильно делать new CSV2TagsTransformer(), потому что таким образом вы не отправляете менеджер сущностей в ваш класс, и, поскольку он не может принять нулевое значение, он потерпит неудачу в PHP.

Надеюсь, это поможет.

С уважением,
Matt

1 голос
/ 11 декабря 2011

Что касается вашей основной проблемы, в вашем файле services.yml вы должны пометить свой сервис как form.type, например:

services:
    jm.blog.csv2tagsTransformer:
        class: JM\BlogBundle\Form\DataTransformer\CSV2TagsTransformer
        arguments: ["@doctrine.orm.entity_manager"]
        tags:
          - { name: form.type, alias: csv2tags }

Что касается других проблем, я понятия не имею.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...