在 Doctrine 中不被读取为 nullable

nullable not being read in Doctrine

我有一个来自 Skeleton 应用程序的 Zend Expressive 项目。此外,为我设置为可为空的每个字段设置了数据库 NOT NULL。我认为这可能与它不阅读注释有关。我首先遇到了让注释工作的问题,特别是对于 cli-config.php

这是我根据我发现的一个例子粗略创建的 DoctrineFactory。我更改了它创建 entityManager 的方式,以更接近地代表 Doctrine 文档配置示例。

public function __invoke(ContainerInterface $container)
{
    $config = $container->has('config') ? $container->get('config') : [];
    $proxyDir = (isset($config['doctrine']['orm']['proxy_dir'])) ?
        $config['doctrine']['orm']['proxy_dir'] : 'data/cache/EntityProxy';
    $proxyNamespace = (isset($config['doctrine']['orm']['proxy_namespace'])) ?
        $config['doctrine']['orm']['proxy_namespace'] : 'EntityProxy';
    $autoGenerateProxyClasses = (isset($config['doctrine']['orm']['auto_generate_proxy_classes'])) ?
        $config['doctrine']['orm']['auto_generate_proxy_classes'] : false;
    $underscoreNamingStrategy = (isset($config['doctrine']['orm']['underscore_naming_strategy'])) ?
        $config['doctrine']['orm']['underscore_naming_strategy'] : false;

    $paths = (isset($config['doctrine']['paths'])) ? $config['doctrine']['paths'] : [];
    $isDevMode = (isset($config['doctrine']['isDevMode'])) ? $config['doctrine']['isDevMode'] : false;

    $doctrine = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);

    // Doctrine ORM
    $doctrine->setProxyDir($proxyDir);
    $doctrine->setProxyNamespace($proxyNamespace);
    $doctrine->setAutoGenerateProxyClasses($autoGenerateProxyClasses);
    if ($underscoreNamingStrategy) {
        $doctrine->setNamingStrategy(new UnderscoreNamingStrategy());
    }

    // Cache
    $cache = $container->get(Cache::class);
    $doctrine->setQueryCacheImpl($cache);
    $doctrine->setResultCacheImpl($cache);
    $doctrine->setMetadataCacheImpl($cache);

    // EntityManager
    return EntityManager::create($config['doctrine']['connection']['orm_default'], $doctrine);
}

配置如下:

'doctrine' => [
    'orm'        => [
        'auto_generate_proxy_classes' => false,
        'proxy_dir'                   => 'data/cache/EntityProxy',
        'proxy_namespace'             => 'EntityProxy',
        'underscore_naming_strategy'  => true,
    ],
    'connection' => [
        // default connection
        'orm_default' => [
            'driver'   => 'pdo_mysql',
            'host'     => '127.0.0.1',
            'port'     => '3306',
            'dbname'   => 'users',
            'user'     => 'root',
            'password' => 'password',
            'charset'  => 'UTF8',
        ],
    ],
    'paths' => [
        __DIR__.'/../../vendor/plexus/user-lib/src/Entity'
    ],
    'isDevMode' => false,
    'cache'      => [
        'redis' => [
            'host' => '127.0.0.1',
            'port' => '6379',
        ],
    ],
],

实体:

namespace Plexus\User\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 */
class User
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(name="id", type="int")
     * @var int
     */
    protected $id;

    /**
     * @ORM\Column(name="email", type="string", length=255)
     * @var string
     */
    protected $email;

    /**
     * @ORM\Column(name="unverifiedEmail", type="string", length=255, nullable=true)
     * @var string
     */
    protected $unverifiedEmail;

    /**
     * @ORM\Column(name="unverifiedEmailHash", type="string", length=255, nullable=true)
     * @var string
     */
    protected $verifyEmailHash;

    /**
     * @var string
     * At this time, http://php.net/manual/en/function.password-hash.php recommends using 255 length for hashes
     * @ORM\Column(name="passwordHash", type="string", length=255)
     */
    protected $passwordHash;

    /**
     * @var string
     * @ORM\Column(name="passwordResetHash", type="string", length=255, nullable=true)
     */
    protected $passwordResetHash;

    /**
     * @return mixed
     */
    public function getUnverifiedEmail()
    {
        return $this->unverifiedEmail;
    }

    /**
     * @param mixed $unverifiedEmail
     */
    public function setUnverifiedEmail($unverifiedEmail)
    {
        $this->unverifiedEmail = $unverifiedEmail;
    }

    /**
     * @return mixed
     */
    public function getVerifyEmailHash()
    {
        return $this->verifyEmailHash;
    }

    /**
     * @param mixed $verifyEmailHash
     */
    public function setVerifyEmailHash($verifyEmailHash)
    {
        $this->verifyEmailHash = $verifyEmailHash;
    }

    /**
     * @return string
     */
    public function getEmail()
    {
        return $this->email;
    }

    /**
     * @param string $email
     */
    public function setEmail($email)
    {
        $this->email = $email;
    }

    /**
     * @return string
     */
    public function getPasswordHash()
    {
        return $this->passwordHash;
    }

    /**
     * @param string $passwordHash
     */
    public function setPasswordHash($passwordHash)
    {
        $this->passwordHash = $passwordHash;
    }

    /**
     * @return string
     */
    public function getPasswordResetHash(): string
    {
        return $this->passwordResetHash;
    }

    /**
     * @param string $passwordResetHash
     */
    public function setPasswordResetHash(string $passwordResetHash)
    {
        $this->passwordResetHash = $passwordResetHash;
    }

    /**
     * @return mixed
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @param mixed $id
     */
    public function setId($id)
    {
        $this->id = $id;
    }

    public function toArray()
    {
        return [
            'email' => $this->getEmail(),
        ];
    }
}

错误:

   Doctrine\DBAL\Exception\NotNullConstraintViolationException: An exception occurred while executing 'INSERT INTO user (unverifiedEmail, unverifiedEmailHash, passwordHash, passwordResetHash) VALUES (?, ?, ?, ?)' with params [null, null, "y$pRDv8NFXaCxF7\/ZUzL.ZuulsFqdwTs9IOycWTHYA.1Q0qpFu5uGXe", null]:

        SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'unverifiedEmail' cannot be null in file /var/www/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php on line 118
    Stack trace:
  1. Doctrine\DBAL\Exception\NotNullConstraintViolationException->() /var/www/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php:118
  2. Doctrine\DBAL\Driver\AbstractMySQLDriver->convertException() /var/www/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php:176
  3. Doctrine\DBAL\DBALException->wrapException() /var/www/vendor/doctrine/dbal/lib/Doctrine/DBAL/DBALException.php:150
  4. Doctrine\DBAL\DBALException->driverExceptionDuringQuery() /var/www/vendor/doctrine/dbal/lib/Doctrine/DBAL/Statement.php:177
  5. Doctrine\DBAL\Driver\PDOException->() /var/www/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php:107
  6. PDOException->() /var/www/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php:105
  7. PDOStatement->execute() /var/www/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php:105
  8. Doctrine\DBAL\Driver\PDOStatement->execute() /var/www/vendor/doctrine/dbal/lib/Doctrine/DBAL/Statement.php:168
  9. Doctrine\DBAL\Statement->execute() /var/www/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/Entity/BasicEntityPersister.php:283
 10. Doctrine\ORM\Persisters\Entity\BasicEntityPersister->executeInserts() /var/www/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:1051
 11. Doctrine\ORM\UnitOfWork->executeInserts() /var/www/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:386
 12. Doctrine\ORM\UnitOfWork->commit() /var/www/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php:358
 13. Doctrine\ORM\EntityManager->flush() /var/www/vendor/plexus/user-lib/src/Service/UserServiceDoctrine.php:53
 14. Plexus\User\Service\UserServiceDoctrine->saveUser() /var/www/vendor/plexus/user-lib/src/Service/UserService.php:27
 15. Plexus\User\Service\UserService->setPassword() /var/www/vendor/plexus/user-lib/src/Service/UserServiceDoctrine.php:43
 16. Plexus\User\Service\UserServiceDoctrine->createUser() /var/www/src/App/src/Action/CreateUserAction.php:39
 17. App\Action\CreateUserAction->process() /var/www/vendor/zendframework/zend-expressive/src/Middleware/LazyLoadingMiddleware.php:62
...

如有任何帮助,我们将不胜感激。我想不出是什么原因造成的。

事实证明,问题是 Doctrine 正在缓存我的实体,并且可能持有一个陈旧的实体。我想通了,因为我添加了 id 字段,但它根本没有出现。我销毁并重新创建了我的 Vagrant 盒子,它起作用了。

所以我在缓存适配器周围添加了这个 if 语句:

if (!$isDevMode) {
    // Cache
    $cache = $container->get(Cache::class);
    $doctrine->setQueryCacheImpl($cache);
    $doctrine->setResultCacheImpl($cache);
    $doctrine->setMetadataCacheImpl($cache);
}

然后我将 $isDevMode 设置为 true。