I have a Zend Expressive project from Skeleton app. Also, the database NOT NULL is set for each of the fields that I have set nullable on. I think it might have something to do with it not reading the annotations. I had issues getting the annotations working in the first place, especially for the cli-config.php
Here's the DoctrineFactory I created loosely based on one I found as an example. I changed the way it creates the entityManager to more closely represent the Doctrine docs config example.
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);
}
Config like so:
'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',
],
],
],
Entity:
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(),
];
}
}
Error:
Doctrine\DBAL\Exception\NotNullConstraintViolationException: An exception occurred while executing 'INSERT INTO user (unverifiedEmail, unverifiedEmailHash, passwordHash, passwordResetHash) VALUES (?, ?, ?, ?)' with params [null, null, "$2y$10$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
...
Any help would be greatly appreciated. I can't think of what would cause this.
So the issue, it turns out, is that Doctrine was caching my entities and probably had a hold of a stale entity. I figured this out because I added the id field but it wasn't showing up at all. I destroyed and recreated my Vagrant box, and it worked.
So I added this if statement around the cache adapter:
if (!$isDevMode) {
// Cache
$cache = $container->get(Cache::class);
$doctrine->setQueryCacheImpl($cache);
$doctrine->setResultCacheImpl($cache);
$doctrine->setMetadataCacheImpl($cache);
}
and I set $isDevMode
to true.