I'd like to use Doctrine 2 combined with "l3pp4rd/DoctrineExtensions" in my Zend Framework-Application. But I only get the following error message:
The annotation "@Doctrine\ORM\Mapping\Entity" in class Entities\USER_User does not exist, or could not be auto-loaded.
application\bootstrap.php
protected function _initDoctrine() {
require_once('Doctrine/Common/ClassLoader.php');
$autoloader = Zend_Loader_Autoloader::getInstance();
$classLoader = array(new \Doctrine\Common\ClassLoader('Doctrine'), 'loadClass');
$autoloader->pushAutoloader($classLoader, 'Doctrine\\');
$classLoader = new \Doctrine\Common\ClassLoader('Entities',
realpath(Zend_Registry::get('config')->resources->entityManager->connection->entities), 'loadClass');
$autoloader->pushAutoloader(array($classLoader, 'loadClass'), 'Entities');
$classLoader = new \Doctrine\Common\ClassLoader('Repositories',
realpath(Zend_Registry::get('config')->resources->entityManager->connection->entities), 'loadClass');
$autoloader->pushAutoloader(array($classLoader, 'loadClass'), 'Repositories');
}
library\My\Resource\Entitymanager.php found at http://www.gediminasm.org/article/annotation-reference
class My_Resource_Entitymanager extends Zend_Application_Resource_ResourceAbstract
{
public function init()
{
// WARNING: setup, assumes that autoloaders are set
// configuration settings from the application.ini file
$zendConfig = new Zend_Config($this->getOptions());
// globally used cache driver, in production use APC or memcached
$cache = new Doctrine\Common\Cache\ArrayCache;
// standard annotation reader
$annotationReader = new Doctrine\Common\Annotations\AnnotationReader;
$cachedAnnotationReader = new Doctrine\Common\Annotations\CachedReader(
$annotationReader, // use reader
$cache // and a cache driver
);
// create a driver chain for metadata reading
$driverChain = new Doctrine\ORM\Mapping\Driver\DriverChain();
// load superclass metadata mapping only, into driver chain
// also registers Gedmo annotations.NOTE: you can personalize it
Gedmo\DoctrineExtensions::registerAbstractMappingIntoDriverChainORM(
$driverChain, // our metadata driver chain, to hook into
$cachedAnnotationReader // our cached annotation reader
);
// now we want to register our application entities,
// for that we need another metadata driver used for Entity namespace
$annotationDriver = new Doctrine\ORM\Mapping\Driver\AnnotationDriver(
$cachedAnnotationReader, // our cached annotation reader
$zendConfig->connection->entities // paths to look in
);
// NOTE: driver for application Entity can be different, Yaml, Xml or whatever
// register annotation driver for our application Entity namespace
$driverChain->addDriver($annotationDriver, 'Entities');
// general ORM configuration
$config = new Doctrine\ORM\Configuration;
$config->setProxyDir($zendConfig->connection->proxies->location);
$config->setProxyNamespace($zendConfig->connection->proxies->ns);
$config->setAutoGenerateProxyClasses($zendConfig->connection->proxies->generate); // this can be based on production config.
// register metadata driver
$config->setMetadataDriverImpl($driverChain);
// use our allready initialized cache driver
$config->setMetadataCacheImpl($cache);
$config->setQueryCacheImpl($cache);
// create event manager and hook prefered extension listeners
$evm = new Doctrine\Common\EventManager();
// gedmo extension listeners, remove which are not used
// sluggable
$sluggableListener = new Gedmo\Sluggable\SluggableListener;
// you should set the used annotation reader to listener, to avoid creating new one for mapping drivers
$sluggableListener->setAnnotationReader($cachedAnnotationReader);
$evm->addEventSubscriber($sluggableListener);
// tree
$treeListener = new Gedmo\Tree\TreeListener;
$treeListener->setAnnotationReader($cachedAnnotationReader);
$evm->addEventSubscriber($treeListener);
// loggable, not used in example
$loggableListener = new Gedmo\Loggable\LoggableListener;
$loggableListener->setAnnotationReader($cachedAnnotationReader);
$evm->addEventSubscriber($loggableListener);
// timestampable
$timestampableListener = new Gedmo\Timestampable\TimestampableListener;
$timestampableListener->setAnnotationReader($cachedAnnotationReader);
$evm->addEventSubscriber($timestampableListener);
// translatable
$translatableListener = new Gedmo\Translatable\TranslatableListener;
// current translation locale should be set from session or hook later into the listener
// most important, before entity manager is flushed
$translatableListener->setTranslatableLocale('en');
$translatableListener->setDefaultLocale('en');
$translatableListener->setAnnotationReader($cachedAnnotationReader);
$evm->addEventSubscriber($translatableListener);
// sortable, not used in example
$sortableListener = new Gedmo\Sortable\SortableListener;
$sortableListener->setAnnotationReader($cachedAnnotationReader);
$evm->addEventSubscriber($sortableListener);
// mysql set names UTF-8 if required
$evm->addEventSubscriber(new Doctrine\DBAL\Event\Listeners\MysqlSessionInit());
// DBAL connection
$connection = array(
'driver' => "{$zendConfig->connection->driver}",
'host' => "{$zendConfig->connection->host}",
'dbname' => "{$zendConfig->connection->dbname}",
'user' => "{$zendConfig->connection->user}",
'password' => "{$zendConfig->connection->password}"
);
// Finally, create entity manager
$em = Doctrine\ORM\EntityManager::create($connection, $config, $evm);
Zend_Registry::set('em', $em);
return $em;
}
}
application\models\USER_User.php
namespace Entities;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\HasLifecycleCallbacks
*/
class USER_User
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* Retrieve user id
*/
public function getId()
{
return $this->id;
}
}
application\configs\application.ini
...
includePaths.library = APPLICATION_PATH "/../library/Doctrine"
...
pluginPaths.My_Resource = "My/Resource"
...
autoloaderNamespaces[] = "Doctrine"
autoloaderNamespaces[] = "Gedmo"
autoloaderNamespaces[] = "Symfony"
autoloaderNamespaces[] = "My"
...
resources.entityManager.connection.driver = "pdo_mysql"
resources.entityManager.connection.host = "localhost"
resources.entityManager.connection.dbname = "test"
resources.entityManager.connection.user = "test"
resources.entityManager.connection.password = "test"
resources.entityManager.connection.entities = APPLICATION_PATH "/models"
resources.entityManager.connection.proxies.location = APPLICATION_PATH "/models/Proxies"
resources.entityManager.connection.proxies.ns = "Proxies"
; According to Doctrine manual, this should be true for
; development, and false for production
resources.entityManager.connection.proxies.generate = true
...
Any ideas to get this working?
Solved with the answer of this question: doctrine2 autloader with cli must use AnnotationRegistry
added to library\My\Resource\Entitymanager.php
use Doctrine\Common\Annotations\AnnotationRegistry;
class My_Resource_Entitymanager extends Zend_Application_Resource_ResourceAbstract
{
public function init()
{
AnnotationRegistry::registerFile(__DIR__ . '/../../Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php');
// WARNING: setup, assumes that autoloaders are set
// configuration settings from the application.ini file
...
I also removed
$classLoader = array(new \Doctrine\Common\ClassLoader('Doctrine'), 'loadClass');
$autoloader->pushAutoloader($classLoader, 'Doctrine\\');
from application\bootstrap.php
Thanks for reading my question!
I just had the same issue with Zend Framework 2 and the solution is nearly the same. Just ensure to execute the above statement during application setup. This can be easily done in your Module.php:
class Module
{
// ...
/**
* Event being executed on bootstrap
*/
public function onBootstrap(Event $e)
{
AnnotationRegistry::registerFile('path/to/ORM/Mapping/Driver/DoctrineAnnotations.php');
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With