Доктрина сходит с ума, когда я включаю php opcache на


У меня действительно странная проблема с Доктриной и PHP 5.5.6 Opcache. Все работает просто отлично, когда модуль opcache выключен. Как только я включаю его, я начинаю получать следующее исключение:

Fatal error: Uncaught exception 'Doctrine\ORM\Mapping\MappingException' with message 'Class "Admin\Models\Users\Role" is not a valid entity or mapped super class.' in vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/MappingException.php on line 336
( ! ) Doctrine\ORM\Mapping\MappingException: Class "Admin\Models\Users\Role" is not a valid entity or mapped super class. in vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/MappingException.php on line 336
Call Stack
#   Time    Memory  Function    Location
1   0.0000  128016  {main}( )   ../app.php:0
2   0.0185  615020  Core\Bootstrap->handle( )   ../app.php:53
3   0.0210  695744  call_user_func_array ( )    ../Bootstrap.php:111
4   0.0210  695976  Admin\Controllers\DashboardController->indexAction( )   ../Bootstrap.php:111
5   0.0210  696028  Doctrine\ORM\EntityManager->getRepository( )    ../DashboardController.php:25
6   0.0210  696072  Doctrine\ORM\Repository\DefaultRepositoryFactory->getRepository( )  ../EntityManager.php:759
7   0.0210  696176  Doctrine\ORM\Repository\DefaultRepositoryFactory->createRepository( )   ../DefaultRepositoryFactory.php:50
8   0.0210  696200  Doctrine\ORM\EntityManager->getClassMetadata( ) ../DefaultRepositoryFactory.php:67
9   0.0210  696420  Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory->getMetadataFor( ) ../EntityManager.php:295
10  0.0213  699628  Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory->loadMetadata( )   ../AbstractClassMetadataFactory.php:211
11  0.0224  781128  Doctrine\ORM\Mapping\ClassMetadataFactory->doLoadMetadata( )    ../AbstractClassMetadataFactory.php:318
12  0.0224  782824  Doctrine\ORM\Mapping\Driver\AnnotationDriver->loadMetadataForClass( )   ../ClassMetadataFactory.php:117

Я считаю, что мои сущности определены правильно - как я уже упоминал в начале, как только я отключу opcache, все будет работать должным образом. Для инициализации Доктрины я использую этот фрагмент кода:

// $this->getEntityPaths()   returns an array of existing absolute paths, each of which is checked with realpath().
// $this->getProxyPath()     returns a string with the absolute path, checked with realpath()
// $this->getInDevelopment() returns boolean and is set to TRUE


$config = Setup::createAnnotationMetadataConfiguration($this->getEntityPaths(), $this->getInDevelopment(), $this->getProxyPath());
$config->setAutoGenerateProxyClasses(true);

$dbParams = array(
    'driver'   => 'pdo_pgsql',
    'host'     => $this->getHost(),
    'port'     => $this->getPort(),
    'user'     => $this->getUser(),
    'password' => $this->getPass(),
    'dbname'   => $this->getName()
);

$this->db = EntityManager::create($dbParams, $config);

Я также пробовал эту конфигурацию:

$config = new Configuration;
$config->setProxyDir($this->getProxyPath());
$config->setProxyNamespace('DoctrineProxies');
$config->setAutoGenerateProxyClasses(true);

$driverImpl = $config->newDefaultAnnotationDriver($this->getEntityPaths());

$config->setMetadataDriverImpl($driverImpl);
$config->setMetadataCacheImpl(new \Doctrine\Common\Cache\ArrayCache());
$config->setQueryCacheImpl(new \Doctrine\Common\Cache\ArrayCache());

// the connection configuration
$dbParams = array(
    'driver'   => 'pdo_pgsql',
    'host'     => $this->host,
    'port'     => $this->port,
    'user'     => $this->user,
    'password' => $this->pass,
    'dbname'   => $this->name
);

$this->db = EntityManager::create($dbParams, $config);

Вот сущность

/**
 * Roles
 *
 * @Table(name="roles")
 * @Entity
 */
class Role
{
    /**
     * @Id
     * @Column(name="role_id", type="integer", nullable=false)
     * @GeneratedValue(strategy="IDENTITY")
     */
    private $role_id;


    /**
     * @Column(name="name", type="string", length=100, nullable=false)
     */
    private $name;
}

Для простоты у меня есть AutoGenerateProxyClasses, но просто для уверенности я также протестировал его, сгенерировав прокси. К сожалению, я получаю такое же исключение. Я не уверен, как решить эту проблему и в чем именно заключается проблема. Это ошибка в доктрине? Почему включение OpCache приводит к исключениям Doctrine, а отключение работает нормально? Я что-то пропустил в части конфигурации или сущности?

Author: tftd, 2014-02-21

1 answers

После долгой отладки мне наконец удалось понять, почему Doctrine не работает правильно с включенным OpCache. По-видимому, по умолчанию opcache не хранит и не загружает никаких комментариев, которые у вас есть в вашем php-файле. Как вы можете себе представить, это приводит к множеству необъяснимых исключений в любой библиотеке php, которая полагается на аннотации. Так что просто зайдите в свой php.ini, измените строки ниже, и вы будете как новенький. Я думаю, что это также должно быть включено в помощь Доктрине.

opcache.save_comments=1
opcache.load_comments=1
 7
Author: tftd, 2014-02-23 03:31:13