Doctrine Sluggable — столбец «слаг» не может быть нулевым

Я использую Doctrine с DoctrineExtensions через StofDoctrineExtensionsBundle для автоматического создания слагов, используя поведение «Doctrine Extensions Sluggable».

Слушатель, кажется, зарегистрирован правильно. Поле Entity также помечено как suggable.

При попытке сохранить мою сущность через форму Symfony генерация слагов не происходит. Возникает исключение базы данных.

Исключение:

An exception occurred while executing 'INSERT INTO event (startDate, endDate, title, slug, description, image, followers, city, place) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)' with params ["2017-06-24 20:00:00", "2017-06-26 12:00:00", "Test event name for slug generation", null, "Test", null, null, "Somewhere", "Somewhere else"]:

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'slug' cannot be null

Версии:

PHP                                  7.0.15
symfony/symfony                      v3.2.9
doctrine/doctrine-bundle             1.6.8
doctrine/orm                         v2.5.6
gedmo/doctrine-extensions            v2.4.29
stof/doctrine-extensions-bundle      v1.2.2 

config.yml

doctrine:
    dbal:
        driver: pdo_mysql
        host: '%database_host%'
        port: '%database_port%'
        dbname: '%database_name%'
        user: '%database_user%'
        password: '%database_password%'
        charset: UTF8
    orm:
        auto_generate_proxy_classes: '%kernel.debug%'
        naming_strategy: doctrine.orm.naming_strategy.underscore
        auto_mapping: true

stof_doctrine_extensions:
    default_locale: '%locale%' # pl
    translation_fallback: true
    orm:
        default:
            sluggable: true

Сущность (Event.orm.xml)

<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"
                  xmlns:gedmo="http://Atlantic18.github.io/DoctrineExtensions/schemas/orm/doctrine-extensions-3.0.xsd">
    <entity repository-class="AppBundle\Repository\EventRepository" name="AppBundle\Entity\Event">
        <id name="id" type="integer" column="id">
            <generator strategy="AUTO"/>
        </id>
        <field name="startDate" type="datetime" column="startDate"/>
        <field name="endDate" type="datetime" column="endDate"/>
        <field name="title" type="string" column="title" length="255"/>
        <field name="slug" type="string" column="slug" length="255" unique="true">
            <gedmo:slug unique="true" updatable="true" fields="title" separator="-" />
        </field>
        <field name="description" type="text" column="description" nullable="true"/>
        <field name="image" type="string" column="image" length="255" nullable="true"/>
        <field name="followers" type="integer" column="followers" nullable="true"/>
        <field name="city" type="string" column="city" nullable="false" />
        <field name="place" type="string" column="place" nullable="true" />
    </entity>
</doctrine-mapping>

Действие контроллера:

    public function createAction(Request $request)
    {
        $form = $this->createForm(EventType::class);

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            /** @var Event $event */
            $event = $form->getData();

            $em = $this->getDoctrine()->getManager();
            $em->persist($event);
            $em->flush();

            $this->addFlash('success', 'event created');
            return $this->redirectToRoute('calendar_event', [
                'slug' => $event->getSlug()
            ]);
        }

        return ['form' => $form->createView()];
    }

Полная трассировка стека:

[1] Doctrine\DBAL\Exception\NotNullConstraintViolationException: An exception occurred while executing 'INSERT INTO event (startDate, endDate, title, slug, description, image, followers, city, place) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)' with params ["2017-06-24 20:00:00", "2017-06-26 12:00:00", "Test event name for slug generation", null, "Test", null, null, "Somewhere", "Somewhere else"]:

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'slug' cannot be null
    at n/a
        in /project_home/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php line 112

    at Doctrine\DBAL\Driver\AbstractMySQLDriver->convertException('An exception occurred while executing \'INSERT INTO event (startDate, endDate, title, slug, description, image, followers, city, place) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\' with params ["2017-06-24 20:00:00", "2017-06-26 12:00:00", "Test event name for slug generation", null, "Test", null, null, "Somewhere", "Somewhere else"]:SQLSTATE[23000]: Integrity constraint violation: 1048 Column \'slug\' cannot be null', object(PDOException))
        in /project_home/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php line 128

    at Doctrine\DBAL\DBALException::driverExceptionDuringQuery(object(Driver), object(PDOException), 'INSERT INTO event (startDate, endDate, title, slug, description, image, followers, city, place) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)', array('2017-06-24 20:00:00', '2017-06-26 12:00:00', 'Test event name for slug generation', null, 'Test', null, null, 'Somewhere', 'Somewhere else'))
        in /project_home/vendor/doctrine/dbal/lib/Doctrine/DBAL/Statement.php line 177

    at Doctrine\DBAL\Statement->execute()
        in /project_home/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php line 281

    at Doctrine\ORM\Persisters\Entity\BasicEntityPersister->executeInserts()
        in /project_home/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php line 1014

    at Doctrine\ORM\UnitOfWork->executeInserts(object(ClassMetadata))
        in /project_home/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php line 378

    at Doctrine\ORM\UnitOfWork->commit(null)
        in /project_home/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php line 356

    at Doctrine\ORM\EntityManager->flush(null)
        in /project_home/var/cache/dev/appDevDebugProjectContainer.php line 7072

    at DoctrineORMEntityManager_00000000751279ee000000007e7efeea3473a0393d6fcd1415b2fc588e376308->flush(null)
        in /project_home/var/cache/dev/jms_diextra/doctrine/EntityManager_59394e2cc7d86.php line 313

    at EntityManager59394e2cc7d86_546a8d27f194334ee012bfe64f629947b07e4919\__CG__\Doctrine\ORM\EntityManager->flush()
        in /project_home/src/AppBundle/Controller/CalendarController.php line 56

    at AppBundle\Controller\CalendarController->createAction(object(Request))
        in  line 

    at ReflectionMethod->invokeArgs(object(CalendarController), array(object(Request)))
        in /project_home/vendor/jms/cg/src/CG/Proxy/MethodInvocation.php line 84

    at CG\Proxy\MethodInvocation->proceed()
        in /project_home/vendor/jms/security-extra-bundle/Security/Authorization/Interception/MethodSecurityInterceptor.php line 133

    at JMS\SecurityExtraBundle\Security\Authorization\Interception\MethodSecurityInterceptor->intercept(object(MethodInvocation))
        in /project_home/vendor/jms/cg/src/CG/Proxy/MethodInvocation.php line 79

    at CG\Proxy\MethodInvocation->proceed()
        in /project_home/var/cache/dev/jms_diextra/proxies/AppBundle-Controller-CalendarController.php line 21

    at EnhancedProxye0ff800f_2852d4e43776e45f00f38751350397dbf530e575\__CG__\AppBundle\Controller\CalendarController->createAction(object(Request))
        in  line 

    at call_user_func_array(array(object(CalendarController), 'createAction'), array(object(Request)))
        in /project_home/var/cache/dev/classes.php line 4228

    at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1)
        in /project_home/var/cache/dev/classes.php line 4183

    at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
        in /project_home/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php line 168

    at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
        in /project_home/web/app_dev.php line 28

    at require('/project_home/web/app_dev.php')
        in /project_home/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Resources/config/router_dev.php line 40

[2] Doctrine\DBAL\Driver\PDOException: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'slug' cannot be null
    at n/a
        in /project_home/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php line 93

    at Doctrine\DBAL\Driver\PDOStatement->execute(null)
        in /project_home/vendor/doctrine/dbal/lib/Doctrine/DBAL/Statement.php line 168

    at Doctrine\DBAL\Statement->execute()
        in /project_home/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php line 281

    at Doctrine\ORM\Persisters\Entity\BasicEntityPersister->executeInserts()
        in /project_home/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php line 1014

    at Doctrine\ORM\UnitOfWork->executeInserts(object(ClassMetadata))
        in /project_home/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php line 378

    at Doctrine\ORM\UnitOfWork->commit(null)
        in /project_home/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php line 356

    at Doctrine\ORM\EntityManager->flush(null)
        in /project_home/var/cache/dev/appDevDebugProjectContainer.php line 7072

    at DoctrineORMEntityManager_00000000751279ee000000007e7efeea3473a0393d6fcd1415b2fc588e376308->flush(null)
        in /project_home/var/cache/dev/jms_diextra/doctrine/EntityManager_59394e2cc7d86.php line 313

    at EntityManager59394e2cc7d86_546a8d27f194334ee012bfe64f629947b07e4919\__CG__\Doctrine\ORM\EntityManager->flush()
        in /project_home/src/AppBundle/Controller/CalendarController.php line 56

    at AppBundle\Controller\CalendarController->createAction(object(Request))
        in  line 

    at ReflectionMethod->invokeArgs(object(CalendarController), array(object(Request)))
        in /project_home/vendor/jms/cg/src/CG/Proxy/MethodInvocation.php line 84

    at CG\Proxy\MethodInvocation->proceed()
        in /project_home/vendor/jms/security-extra-bundle/Security/Authorization/Interception/MethodSecurityInterceptor.php line 133

    at JMS\SecurityExtraBundle\Security\Authorization\Interception\MethodSecurityInterceptor->intercept(object(MethodInvocation))
        in /project_home/vendor/jms/cg/src/CG/Proxy/MethodInvocation.php line 79

    at CG\Proxy\MethodInvocation->proceed()
        in /project_home/var/cache/dev/jms_diextra/proxies/AppBundle-Controller-CalendarController.php line 21

    at EnhancedProxye0ff800f_2852d4e43776e45f00f38751350397dbf530e575\__CG__\AppBundle\Controller\CalendarController->createAction(object(Request))
        in  line 

    at call_user_func_array(array(object(CalendarController), 'createAction'), array(object(Request)))
        in /project_home/var/cache/dev/classes.php line 4228

    at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1)
        in /project_home/var/cache/dev/classes.php line 4183

    at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
        in /project_home/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php line 168

    at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
        in /project_home/web/app_dev.php line 28

    at require('/project_home/web/app_dev.php')
        in /project_home/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Resources/config/router_dev.php line 40

[3] PDOException: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'slug' cannot be null
    at n/a
        in /project_home/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php line 91

    at PDOStatement->execute(null)
        in /project_home/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php line 91

    at Doctrine\DBAL\Driver\PDOStatement->execute(null)
        in /project_home/vendor/doctrine/dbal/lib/Doctrine/DBAL/Statement.php line 168

    at Doctrine\DBAL\Statement->execute()
        in /project_home/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php line 281

    at Doctrine\ORM\Persisters\Entity\BasicEntityPersister->executeInserts()
        in /project_home/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php line 1014

    at Doctrine\ORM\UnitOfWork->executeInserts(object(ClassMetadata))
        in /project_home/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php line 378

    at Doctrine\ORM\UnitOfWork->commit(null)
        in /project_home/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php line 356

    at Doctrine\ORM\EntityManager->flush(null)
        in /project_home/var/cache/dev/appDevDebugProjectContainer.php line 7072

    at DoctrineORMEntityManager_00000000751279ee000000007e7efeea3473a0393d6fcd1415b2fc588e376308->flush(null)
        in /project_home/var/cache/dev/jms_diextra/doctrine/EntityManager_59394e2cc7d86.php line 313

    at EntityManager59394e2cc7d86_546a8d27f194334ee012bfe64f629947b07e4919\__CG__\Doctrine\ORM\EntityManager->flush()
        in /project_home/src/AppBundle/Controller/CalendarController.php line 56

    at AppBundle\Controller\CalendarController->createAction(object(Request))
        in  line 

    at ReflectionMethod->invokeArgs(object(CalendarController), array(object(Request)))
        in /project_home/vendor/jms/cg/src/CG/Proxy/MethodInvocation.php line 84

    at CG\Proxy\MethodInvocation->proceed()
        in /project_home/vendor/jms/security-extra-bundle/Security/Authorization/Interception/MethodSecurityInterceptor.php line 133

    at JMS\SecurityExtraBundle\Security\Authorization\Interception\MethodSecurityInterceptor->intercept(object(MethodInvocation))
        in /project_home/vendor/jms/cg/src/CG/Proxy/MethodInvocation.php line 79

    at CG\Proxy\MethodInvocation->proceed()
        in /project_home/var/cache/dev/jms_diextra/proxies/AppBundle-Controller-CalendarController.php line 21

    at EnhancedProxye0ff800f_2852d4e43776e45f00f38751350397dbf530e575\__CG__\AppBundle\Controller\CalendarController->createAction(object(Request))
        in  line 

    at call_user_func_array(array(object(CalendarController), 'createAction'), array(object(Request)))
        in /project_home/var/cache/dev/classes.php line 4228

    at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1)
        in /project_home/var/cache/dev/classes.php line 4183

    at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
        in /project_home/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php line 168

    at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
        in /project_home/web/app_dev.php line 28

    at require('/project_home/web/app_dev.php')
        in /project_home/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Resources/config/router_dev.php line 40

person Kacper    schedule 12.06.2017    source источник
comment
Вам не нужно включать весь код, чтобы понять, что сообщение об ошибке, которое вы получаете: Column 'slug' cannot be null — это именно то, что оно говорит: схема БД не допускает null значений для этого столбца!   -  person Koby Douek    schedule 12.06.2017
comment
@KobyDouek слаг должен генерироваться автоматически с помощью расширения Doctrine ORM Sluggable. Вот так. Это поле должно быть заполнено слушателем Sluggable   -  person Kacper    schedule 12.06.2017
comment
@Kacper единственная разница, которую я вижу, заключается в объявлении вашего пространства имен xml. Вы ссылаетесь на URL версии 3.x, используя версию 2.x. В официальной документации используется эта схема http://gediminasm.org/schemas/orm/doctrine-extensions-mapping   -  person lordrhodos    schedule 15.06.2017
comment
@lordrhodos на самом деле, изменение URL-адреса XML-схемы решило проблему! Опубликуйте это как решение, чтобы я мог дать вам награду!   -  person Kacper    schedule 20.06.2017


Ответы (3)


Единственная разница, которую я вижу, заключается в объявлении вашего пространства имен xml. Вы ссылаетесь на версию 3.x, используя версию 2.x. Официальная документация использует эту схему

http://gediminasm.org/schemas/orm/doctrine-extensions-mappin‌​g

обязательно обновите отображение xml соответствующим образом:

<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"
                  xmlns:gedmo="http://gediminasm.org/schemas/orm/doctrine-extensions-mappin‌​g">
    <entity repository-class="AppBundle\Repository\EventRepository" name="AppBundle\Entity\Event">
        <id name="id" type="integer" column="id">
            <generator strategy="AUTO"/>
        </id>
        <field name="startDate" type="datetime" column="startDate"/>
        <field name="endDate" type="datetime" column="endDate"/>
        <field name="title" type="string" column="title" length="255"/>
        <field name="slug" type="string" column="slug" length="255" unique="true">
            <gedmo:slug unique="true" updatable="true" fields="title" separator="-" />
        </field>
        <field name="description" type="text" column="description" nullable="true"/>
        <field name="image" type="string" column="image" length="255" nullable="true"/>
        <field name="followers" type="integer" column="followers" nullable="true"/>
        <field name="city" type="string" column="city" nullable="false" />
        <field name="place" type="string" column="place" nullable="true" />
    </entity>
</doctrine-mapping>
person lordrhodos    schedule 20.06.2017
comment
Рад, что смог помочь. Большое спасибо за щедрость! - person lordrhodos; 20.06.2017

Когда я реализовал StofDoctrineExtensionsBundle, я впервые выполнил функцию, которая установила все значения slug в null. (Когда для slug установлено значение null, прослушиватель вызывается, значение slug заполняется.

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

person Zuhayer Tahir    schedule 19.06.2017
comment
Вызов $entity->setSlug(null) вручную не помогает, к сожалению - person Kacper; 20.06.2017

Как говорит вам исключение:

'slug' cannot be null

Вам нужно изменить определение свойства в Event.orm.xml и сделать слаг обнуляемым, поскольку по умолчанию он имеет значение nullable false.

Итак, вам нужно изменить свое определение следующим образом:

        <field name="slug" type="string" column="slug" length="255" unique="true" nullable="false">
            <gedmo:slug unique="true" updatable="true" fields="title" separator="-" />
        </field>

Это разрешит ваше исключение. Но реальная проблема заключается в уникальном ограничении свойства slug: во второй раз, когда вы вставите событие со значением «null», оно активирует уникальное ограничение, потому что уже есть строка с нулевым slug. Таким образом, вам нужно предоставить слаг или удалить уникальное ограничение.

person Marwen Cherif    schedule 12.06.2017
comment
Что ж, расширение Doctrine Sluggable должно предоставить «слаг». Я попытался установить nullable на true и сбросить ограничение unique. Дело в том, что слаг не генерируется DoctrineExtensions. - person Kacper; 12.06.2017