Symfony 3.3 + Doctrine/MongoDB: регистрация пользовательского типа сопоставления

Начиная с Symfony 3.3 файл app/autoload.php исчез. Но я использовал его для регистрации пользовательского типа сопоставления, как описано здесь.

Мой текущий app/autoload.php выглядит так:

use Doctrine\Common\Annotations\AnnotationRegistry;
use Composer\Autoload\ClassLoader;
use Doctrine\ODM\MongoDB\Mapping\Driver\AnnotationDriver;
use Doctrine\ODM\MongoDB\Types\Type;

/** @var ClassLoader $loader */
$loader = require __DIR__.'/../vendor/autoload.php';

Type::addType("MyCustomType", "Com\\MyBundle\\Db\\MyCustomTypeClass");
AnnotationRegistry::registerLoader([$loader, 'loadClass']);
AnnotationDriver::registerAnnotationClasses();

return $loader;

Как указано здесь, AnnotationDriver::registerAnnotationClasses(); больше не нужно вызывать с Symfony 3.3. Но я не знаю, куда положить

Type::addType("MyCustomType", "Com\\MyBundle\\Db\\MyCustomTypeClass");

Я попытался поместить его в метод boot() класса MyBundle, который расширяет Bundle. Но когда я впервые запускаю свои модульные тесты после применения изменения, я получаю InvalidArgumentException: Invalid type specified "MyCustomType".. Когда я выполняю их снова, я получаю Doctrine\ODM\MongoDB\Mapping\MappingException: Type MyCustomType already exists..


person Spunc    schedule 12.06.2017    source источник


Ответы (2)


Как указано в официальной документации: http://symfony.com/doc/current/doctrine/dbal.html#registering-custom-mapping-types

# app/config/config.yml
doctrine:
    dbal:
        types:
            my_custom_type:  Com\\MyBundle\\Db\\MyCustomTypeClass
person Jake Litwicki    schedule 12.06.2017
comment
Я использую Doctrine-ODM (для MongoDB), а не Doctrine-ORM. Вы ссылаетесь на руководство Doctrine-ORM. Конфигурация, которую вы показываете, применима только к Doctrine-ORM. Конфигурация Doctrine-ODM начинается с: doctrine_mongodb:. К сожалению, у него нет опции конфигурации dbal:. - person Spunc; 13.06.2017
comment
Ты совершенно прав; виноват! Вы пытались загрузить его в свой метод __construct() в файле класса MyBundle? - person Jake Litwicki; 13.06.2017
comment
Я также пытался поместить код Type::addType в __construct() вместо boot(), но это имело тот же эффект. - person Spunc; 13.06.2017

Я нашел решение своей проблемы здесь. Хотя это решение предназначено для Doctrine-ORM, оно также работает и для Doctrine-ODM (Doctrine/MongoDB).

Он использует тот же подход, который я попробовал первым: поместить вызов Type::addType в метод boot() класса Bundle. Однако сначала он проверяет, существует ли уже этот тип:

public function boot() {
    if(!Type::hasType("MyCustomType")) {
        Type::addType("MyCustomType", "Com\\MyBundle\\Db\\MyCustomTypeClass");
    }
}

Это работает, хотя я не уверен, что это самое элегантное решение.


Изменить:

Хотя казалось, что это работает (модульные тесты работают), он не запускается на сервере. И, похоже, это как-то связано с гидраторами.

  1. Первый вызов bin/console server:run выдает ошибку: Uncaught InvalidArgumentException: Invalid type specified "MyCustomType"
  2. После завершения работы сервера перезапуск сервера работает.
  3. Но затем просмотр любого URL-адреса, сопоставленного с контроллером, снова дает (1/1) InvalidArgumentException Invalid type specified "MyCustomType". (теперь отображается в браузере).
  4. Перезагрузка URL-адреса работает.
  5. На данный момент приложение работает, но перезапуск сервера снова дает проблему, указанную в пункте 1.
person Spunc    schedule 13.06.2017