I needed to configure Doctrine ORM with php. Tried first with CI framework some nights , but it felt like pain in the ass. In the end I started up configuring Doctrine ,Gedmo behavioral Extension with core php.
[STEP 1] Download Doctrine from github
After downloading doctrine orm, i put it under TGCore/app/thirdparty package.
(TGCore is the root folder of my app.)
[STEP 2] Creating Model /app/models/Country.php
<?php
namespace models;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* @ORM\Entity(repositoryClass="models\repository\CountryRepository")
* @ORM\Table(name="Country")
*
*/
class Country{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue
*/
public $id;
/**
* @ORM\Column(type="string", length=255, nullable=false)
*/
public $name;
/**
* @ORM\Column(type="string", length=255)
*/
public $description;
/**
* @var datetime $created
*
* @Gedmo\Timestampable(on="create")
* @ORM\Column(type="datetime")
*/
public $created;
/**
* @ORM\OneToMany(targetEntity="models\City",mappedBy="country")
*/
public $cities;
/**
* @ORM\Column(type="boolean")
*/
public $active;
public function __construct(){
$this->id_type = new ArrayCollection();
}
}
<?php
use Doctrine\Common\ClassLoader,
Doctrine\ORM\Configuration,
Doctrine\ORM\EntityManager,
Doctrine\Common\Cache\ArrayCache,
Doctrine\Common\Annotations\AnnotationReader,
Doctrine\ORM\Mapping\Driver\AnnotationDriver,
Doctrine\DBAL\Logging\EchoSqlLogger,
Doctrine\DBAL\Event\Listeners\MysqlSessionInit,
Doctrine\ORM\Tools\SchemaTool,
Doctrine\ORM\Tools\Setup,
Doctrine\Common\EventManager,
Gedmo\Timestampable\TimestampableListener,
Gedmo\Sluggable\SluggableListener,
Gedmo\Tree\TreeListener,
Gedmo\SoftDeleteable\SoftDeleteableListener,
Gedmo\Loggable\LoggableListener;
include_once(dirname(__FILE__) . '/database.php');
include_once 'app/thirdparty/Doctrine/Common/ClassLoader.php';
include_once 'app/thirdparty/Doctrine/ORM/Tools/Setup.php';
$APP_NAME = "TG";
if($_SERVER['HTTP_HOST'] == "localhost"){
$_CONFIG['base_url'] = "http://localhost/{$APP_NAME}/";
$_CONFIG['base_path'] = $_SERVER['DOCUMENT_ROOT'] . "/{$APP_NAME}/";
}else{
$_CONFIG['base_url'] = "http://localhost/{$APP_NAME}/";
$_CONFIG['base_path'] = $_SERVER['DOCUMENT_ROOT'] . "/{$APP_NAME}/";
}
define('ROOT_HOST', $_CONFIG['base_url']);
define('ROOT_DIR', $_CONFIG['base_path']);
/*********** Define the values *********/
define("HOSTNAME", $db['hostname']);
define("USERNAME", $db['username']);
define("PASSWORD", $db['password']);
define("DATABASE", $db['database']);
define("BASE_URL", ROOT_HOST);
$application_folder = 'app';
define('APPPATH', ROOT_DIR.$application_folder.'/');
define('EXT', '.php');
/**
*
* @var Doctrine\ORM\EntityManager
*/
$em = null;
/*bootstrapping doctrine*/
// Set up class loading
$doctrineClassLoader = new ClassLoader('Doctrine', APPPATH.'thirdparty');
$doctrineClassLoader->register();
// Setting up Gedmo
$classLoader = new ClassLoader('Gedmo', APPPATH.'thirdparty');
$classLoader->register();
// Setting up custom extensions
$zExtensionsLoader = new ClassLoader('zamoon', APPPATH.'thirdparty');
$zExtensionsLoader->register();
// Setting up models loading
$entitiesClassLoader = new ClassLoader('models', APPPATH);
$entitiesClassLoader->register();
$proxiesClassLoader = new ClassLoader('Proxies', APPPATH.'models/proxies');
$proxiesClassLoader->register();
//print ("ensure standard doctrine annotations are registered<br/>");
Doctrine\Common\Annotations\AnnotationRegistry::registerFile(APPPATH.'thirdparty/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php');
// print("Set up caches<br/>");
$ormConfig = new Doctrine\ORM\Configuration;
$arratyCache = new Doctrine\Common\Cache\ArrayCache;
$ormConfig->setMetadataCacheImpl($arratyCache);
$driverImpl = $ormConfig->newDefaultAnnotationDriver(array(APPPATH.'models/'));
$ormConfig->setMetadataDriverImpl($driverImpl);
$ormConfig->setQueryCacheImpl($arratyCache);
$ormConfig->setQueryCacheImpl($arratyCache);
// print("ORM Proxy configuration");
$ormConfig->setProxyDir(APPPATH.'/models/proxies');
$ormConfig->setProxyNamespace('Proxies');
$ormConfig->setAutoGenerateProxyClasses(TRUE); // this can be based on production config.
$evm = new Doctrine\Common\EventManager();
//print("gedmo extension listeners");
// 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);
//loggable
$loggableListener = new Gedmo\Loggable\LoggableListener;
$loggableListener->setAnnotationReader($cachedAnnotationReader);
$evm->addEventSubscriber($loggableListener);
// timestampable
$timestampableListener = new Gedmo\Timestampable\TimestampableListener;
$timestampableListener->setAnnotationReader($cachedAnnotationReader);
$evm->addEventSubscriber($timestampableListener);
//soft delete
$softdeletelistener = new Gedmo\SoftDeleteable\SoftDeleteableListener;
$softdeletelistener->setAnnotationReader($cachedAnnotationReader);
$evm->addEventSubscriber($softdeletelistener);
//setup soft delete filter
$ormConfig->addFilter('soft-deleteable', 'Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter');
// Database connection information
$connectionOptions = array(
'driver' => 'pdo_mysql',
'user' => "root",
'password' => "mysql",
'host' => "localhost",
'dbname' => "TG"
);
//central access point to ORM functionality.
$em = EntityManager::create($connectionOptions, $ormConfig, $evm);
//create/drop/update database schemas based on <tt>ClassMetadata</tt> class descriptors.
$tool = new SchemaTool($em);
if($em){
//ORM metadata descriptor for a class.
$schemas = array(
$em->getClassMetadata('models\Country')
);
}
//Create the databaseschema for the given array of ClassMetadata instances.
$tool->createSchema($this->schemas);
/* End of file config.php */
/* Location: ./app/config/config.php */
[STEP 1] Download Doctrine from github
After downloading doctrine orm, i put it under TGCore/app/thirdparty package.
(TGCore is the root folder of my app.)
[STEP 2] Creating Model /app/models/Country.php
<?php
namespace models;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* @ORM\Entity(repositoryClass="models\repository\CountryRepository")
* @ORM\Table(name="Country")
*
*/
class Country{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue
*/
public $id;
/**
* @ORM\Column(type="string", length=255, nullable=false)
*/
public $name;
/**
* @ORM\Column(type="string", length=255)
*/
public $description;
/**
* @var datetime $created
*
* @Gedmo\Timestampable(on="create")
* @ORM\Column(type="datetime")
*/
public $created;
/**
* @ORM\OneToMany(targetEntity="models\City",mappedBy="country")
*/
public $cities;
/**
* @ORM\Column(type="boolean")
*/
public $active;
public function __construct(){
$this->id_type = new ArrayCollection();
}
}
[STEP 3] Configuring Doctrine - /app/config/config.php
<?php
use Doctrine\Common\ClassLoader,
Doctrine\ORM\Configuration,
Doctrine\ORM\EntityManager,
Doctrine\Common\Cache\ArrayCache,
Doctrine\Common\Annotations\AnnotationReader,
Doctrine\ORM\Mapping\Driver\AnnotationDriver,
Doctrine\DBAL\Logging\EchoSqlLogger,
Doctrine\DBAL\Event\Listeners\MysqlSessionInit,
Doctrine\ORM\Tools\SchemaTool,
Doctrine\ORM\Tools\Setup,
Doctrine\Common\EventManager,
Gedmo\Timestampable\TimestampableListener,
Gedmo\Sluggable\SluggableListener,
Gedmo\Tree\TreeListener,
Gedmo\SoftDeleteable\SoftDeleteableListener,
Gedmo\Loggable\LoggableListener;
include_once(dirname(__FILE__) . '/database.php');
include_once 'app/thirdparty/Doctrine/Common/ClassLoader.php';
include_once 'app/thirdparty/Doctrine/ORM/Tools/Setup.php';
$APP_NAME = "TG";
if($_SERVER['HTTP_HOST'] == "localhost"){
$_CONFIG['base_url'] = "http://localhost/{$APP_NAME}/";
$_CONFIG['base_path'] = $_SERVER['DOCUMENT_ROOT'] . "/{$APP_NAME}/";
}else{
$_CONFIG['base_url'] = "http://localhost/{$APP_NAME}/";
$_CONFIG['base_path'] = $_SERVER['DOCUMENT_ROOT'] . "/{$APP_NAME}/";
}
define('ROOT_HOST', $_CONFIG['base_url']);
define('ROOT_DIR', $_CONFIG['base_path']);
/*********** Define the values *********/
define("HOSTNAME", $db['hostname']);
define("USERNAME", $db['username']);
define("PASSWORD", $db['password']);
define("DATABASE", $db['database']);
define("BASE_URL", ROOT_HOST);
$application_folder = 'app';
define('APPPATH', ROOT_DIR.$application_folder.'/');
define('EXT', '.php');
/**
*
* @var Doctrine\ORM\EntityManager
*/
$em = null;
/*bootstrapping doctrine*/
// Set up class loading
$doctrineClassLoader = new ClassLoader('Doctrine', APPPATH.'thirdparty');
$doctrineClassLoader->register();
// Setting up Gedmo
$classLoader = new ClassLoader('Gedmo', APPPATH.'thirdparty');
$classLoader->register();
// Setting up custom extensions
$zExtensionsLoader = new ClassLoader('zamoon', APPPATH.'thirdparty');
$zExtensionsLoader->register();
// Setting up models loading
$entitiesClassLoader = new ClassLoader('models', APPPATH);
$entitiesClassLoader->register();
$proxiesClassLoader = new ClassLoader('Proxies', APPPATH.'models/proxies');
$proxiesClassLoader->register();
//print ("ensure standard doctrine annotations are registered<br/>");
Doctrine\Common\Annotations\AnnotationRegistry::registerFile(APPPATH.'thirdparty/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php');
// print("Set up caches<br/>");
$ormConfig = new Doctrine\ORM\Configuration;
$arratyCache = new Doctrine\Common\Cache\ArrayCache;
$ormConfig->setMetadataCacheImpl($arratyCache);
$driverImpl = $ormConfig->newDefaultAnnotationDriver(array(APPPATH.'models/'));
$ormConfig->setMetadataDriverImpl($driverImpl);
$ormConfig->setQueryCacheImpl($arratyCache);
$ormConfig->setQueryCacheImpl($arratyCache);
// print("ORM Proxy configuration");
$ormConfig->setProxyDir(APPPATH.'/models/proxies');
$ormConfig->setProxyNamespace('Proxies');
$ormConfig->setAutoGenerateProxyClasses(TRUE); // this can be based on production config.
$evm = new Doctrine\Common\EventManager();
//print("gedmo extension listeners");
// 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);
//loggable
$loggableListener = new Gedmo\Loggable\LoggableListener;
$loggableListener->setAnnotationReader($cachedAnnotationReader);
$evm->addEventSubscriber($loggableListener);
// timestampable
$timestampableListener = new Gedmo\Timestampable\TimestampableListener;
$timestampableListener->setAnnotationReader($cachedAnnotationReader);
$evm->addEventSubscriber($timestampableListener);
//soft delete
$softdeletelistener = new Gedmo\SoftDeleteable\SoftDeleteableListener;
$softdeletelistener->setAnnotationReader($cachedAnnotationReader);
$evm->addEventSubscriber($softdeletelistener);
//setup soft delete filter
$ormConfig->addFilter('soft-deleteable', 'Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter');
// Database connection information
$connectionOptions = array(
'driver' => 'pdo_mysql',
'user' => "root",
'password' => "mysql",
'host' => "localhost",
'dbname' => "TG"
);
//central access point to ORM functionality.
$em = EntityManager::create($connectionOptions, $ormConfig, $evm);
//create/drop/update database schemas based on <tt>ClassMetadata</tt> class descriptors.
$tool = new SchemaTool($em);
if($em){
//ORM metadata descriptor for a class.
$schemas = array(
$em->getClassMetadata('models\Country')
);
}
//Create the databaseschema for the given array of ClassMetadata instances.
$tool->createSchema($this->schemas);
/* End of file config.php */
/* Location: ./app/config/config.php */
ERROR
Fatal error: Uncaught exception 'Doctrine\ORM\Mapping\MappingException' with message 'Class models\Country is not a valid entity or mapped super class.' in /var/www/TGCore/app/thirdparty/Doctrine/ORM/Mapping/MappingException.php:147 Stack trace: #0 /var/www/TGCore/app/thirdparty/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php(165): Doctrine\ORM\Mapping\MappingException::classIsNotAValidEntityOrMappedSuperClass('models\Country') #1 /var/www/TGCore/app/thirdparty/Doctrine/ORM/Mapping/ClassMetadataFactory.php(293): Doctrine\ORM\Mapping\Driver\AnnotationDriver->loadMetadataForClass('models\Country', Object(Doctrine\ORM\Mapping\ClassMetadata)) #2 /var/www/TGCore/app/thirdparty/Doctrine/ORM/Mapping/ClassMetadataFactory.php(178): Doctrine\ORM\Mapping\ClassMetadataFactory->loadMetadata('models\Country') #3 /var/www/TGCore/app/thirdparty/Doctrine/ORM/EntityManager.php(269): Doctrine\ORM\Mapping\ClassMetadataFactory->getMetadataFor('models\Country') #4 /var/www/TGCore/app/config/deve in /var/www/TGCore/app/thirdparty/Doctrine/ORM/Mapping/MappingException.php on line 147
HACK
1 - Debugging Doctrine/ORM/EntityManager.php#getClassMetadata($className)
/**
* Returns the ORM metadata descriptor for a class.
*
* The class name must be the fully-qualified class name without a leading backslash
* (as it is returned by get_class($obj)) or an aliased class name.
*
* Examples:
* TGCore\app\models\Country
* sales:PriceRequest
*
* @return \Doctrine\ORM\Mapping\ClassMetadata
* @internal Performance-sensitive method.
*/
public function getClassMetadata($className){
return $this->metadataFactory->getMetadataFor($className);
}
2 - Debugging Doctrine/ORM/Mapping/ClassMetadataFactory.php#getMetadataFor($className) - not available in Doctrine2 (I guess)
/**
* Gets the class metadata descriptor for a class.
*
* @param string $className The name of the class.
* @return \Doctrine\ORM\Mapping\ClassMetadata
*/
public function getMetadataFor($className){
if ( ! isset($this->loadedMetadata[$className])) {
$realClassName = $className;
// Check for namespace alias
if (strpos($className, ':') !== false) {
list($namespaceAlias, $simpleClassName) = explode(':', $className);
$realClassName = $this->em->getConfiguration()->getEntityNamespace($namespaceAlias) . '\\' . $simpleClassName;
if (isset($this->loadedMetadata[$realClassName])) {
// We do not have the alias name in the map, include it
$this->loadedMetadata[$className] = $this->loadedMetadata[$realClassName];
return $this->loadedMetadata[$realClassName];
}
}
if ($this->cacheDriver) {
if (($cached = $this->cacheDriver->fetch("$realClassName\$CLASSMETADATA")) !== false) {
$this->wakeupReflection($cached, $this->getReflectionService());
$this->loadedMetadata[$realClassName] = $cached;
} else {
foreach ($this->loadMetadata($realClassName) as $loadedClassName) {
$this->cacheDriver->save(
"$loadedClassName\$CLASSMETADATA", $this->loadedMetadata[$loadedClassName], null
);
}
}
} else {
$this->loadMetadata($realClassName);
}
if ($className != $realClassName) {
// We do not have the alias name in the map, include it
$this->loadedMetadata[$className] = $this->loadedMetadata[$realClassName];
}
}
return $this->loadedMetadata[$className];
}
3 - Doctrine/ORM/Mapping/ClassMetadataFactory.php#loadMetaData($realClassName)
/** * Loads the metadata of the class in question and all it's ancestors whose metadata * is still not loaded. * * @param string $name The name of the class for which the metadata should get loaded. * @param array $tables The metadata collection to which the loaded metadata is added. */ protected function loadMetadata($name){ if ( ! $this->initialized) { $this->initialize(); } $loaded = array(); $parentClasses = $this->getParentClasses($name); $parentClasses[] = $name; // Move down the hierarchy of parent classes, starting from the topmost class $parent = null; $rootEntityFound = false; $visited = array(); foreach ($parentClasses as $className) { if (isset($this->loadedMetadata[$className])) { $parent = $this->loadedMetadata[$className]; if ( ! $parent->isMappedSuperclass) { $rootEntityFound = true; array_unshift($visited, $className); } continue; } $class = $this->newClassMetadataInstance($className); $this->initializeReflection($class, $this->getReflectionService()); if ($parent) { $class->setInheritanceType($parent->inheritanceType); $class->setDiscriminatorColumn($parent->discriminatorColumn); $class->setIdGeneratorType($parent->generatorType); $this->addInheritedFields($class, $parent); $this->addInheritedRelations($class, $parent); $class->setIdentifier($parent->identifier); $class->setVersioned($parent->isVersioned); $class->setVersionField($parent->versionField); $class->setDiscriminatorMap($parent->discriminatorMap); $class->setLifecycleCallbacks($parent->lifecycleCallbacks); $class->setChangeTrackingPolicy($parent->changeTrackingPolicy); if ($parent->isMappedSuperclass) { $class->setCustomRepositoryClass($parent->customRepositoryClassName); } } // Invoke driver try { $this->driver->loadMetadataForClass($className, $class);
//In my case, $class = Doctrine\ORM\Mapping\ClassMetadataInfo@00000000222ef1a300000000bfc98980
} catch (ReflectionException $e) {
throw MappingException::reflectionFailure($className, $e);
}
// If this class has a parent the id generator strategy is inherited.
// However this is only true if the hierachy of parents contains the root entity,
// if it consinsts of mapped superclasses these don't necessarily include the id field.
if ($parent && $rootEntityFound) {
if ($parent->isIdGeneratorSequence()) {
$class->setSequenceGeneratorDefinition($parent->sequenceGeneratorDefinition);
} else if ($parent->isIdGeneratorTable()) {
$class->getTableGeneratorDefinition($parent->tableGeneratorDefinition);
}
if ($parent->generatorType) {
$class->setIdGeneratorType($parent->generatorType);
}
if ($parent->idGenerator) {
$class->setIdGenerator($parent->idGenerator);
}
} else {
$this->completeIdGeneratorMapping($class);
}
if ($parent && $parent->isInheritanceTypeSingleTable()) {
$class->setPrimaryTable($parent->table);
}
if ($parent && $parent->containsForeignIdentifier) {
$class->containsForeignIdentifier = true;
}
if ($parent && !empty ($parent->namedQueries)) {
$this->addInheritedNamedQueries($class, $parent);
}
$class->setParentClasses($visited);
if ($this->evm->hasListeners(Events::loadClassMetadata)) {
$eventArgs = new \Doctrine\ORM\Event\LoadClassMetadataEventArgs($class, $this->em);
$this->evm->dispatchEvent(Events::loadClassMetadata, $eventArgs);
}
$this->wakeupReflection($class, $this->getReflectionService());
$this->validateRuntimeMetadata($class, $parent);
$this->loadedMetadata[$className] = $class;
$parent = $class;
if ( ! $class->isMappedSuperclass) {
$rootEntityFound = true;
array_unshift($visited, $className);
}
$loaded[] = $className;
}
return $loaded;
}
4 - Doctrine/ORM/Mapping/Driver/AnnotationDriver.php#loadMetadataForClass($className, ClassMetadataInfo $metadata)
/**
* {@inheritdoc}
*/
public function loadMetadataForClass($className, ClassMetadataInfo $metadata)
{
$class = $metadata->getReflectionClass();
/* it results as follows for me
/**
* @ORM\Entity(repositoryClass="models\repository\CountryRepository")
* @ORM\Table(name="Country")
*
*/
Class [ class models\Country ] {
@@ /var/www/TGCore/app/models/Country.php 10-46
- Constants [0] {}
- Static properties [0] {} - Static methods [0] {} - Properties [6] { Property [ private $id ] Property [ private $name ] Property [ private $description ] Property [ private $created ] Property [ private $cities ] Property [ private $active ] }
*/ if (!$class) { // this happens when running annotation driver in combination with // static reflection services. This is not the nicest fix $class = new \ReflectionClass($metadata->name); } //problem is with _reader (AnnotationReader) i guess $classAnnotations = $this->_reader->getClassAnnotations($class); //in my case returning Array ( )
if ($classAnnotations && is_numeric(key($classAnnotations))) { foreach ($classAnnotations as $annot) { $classAnnotations[get_class($annot)] = $annot; } } // Evaluate Entity annotation
//this is where my code goes wrong
if (isset($classAnnotations['Doctrine\ORM\Mapping\Entity'])) {
$entityAnnot = $classAnnotations['Doctrine\ORM\Mapping\Entity'];
if ($entityAnnot->repositoryClass !== null) {
$metadata->setCustomRepositoryClass($entityAnnot->repositoryClass);
}
if ($entityAnnot->readOnly) {
$metadata->markReadOnly();
}
} else if (isset($classAnnotations['Doctrine\ORM\Mapping\MappedSuperclass'])) {
$mappedSuperclassAnnot = $classAnnotations['Doctrine\ORM\Mapping\MappedSuperclass'];
$metadata->setCustomRepositoryClass($mappedSuperclassAnnot->repositoryClass);
$metadata->isMappedSuperclass = true;
} else {
throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className);
}
// Evaluate Table annotation
if (isset($classAnnotations['Doctrine\ORM\Mapping\Table'])) {
$tableAnnot = $classAnnotations['Doctrine\ORM\Mapping\Table'];
$primaryTable = array(
'name' => $tableAnnot->name,
'schema' => $tableAnnot->schema
);
if ($tableAnnot->indexes !== null) {
foreach ($tableAnnot->indexes as $indexAnnot) {
$index = array('columns' => $indexAnnot->columns);
if ( ! empty($indexAnnot->name)) {
$primaryTable['indexes'][$indexAnnot->name] = $index;
} else {
$primaryTable['indexes'][] = $index;
}
}
}
if ($tableAnnot->uniqueConstraints !== null) {
foreach ($tableAnnot->uniqueConstraints as $uniqueConstraintAnnot) {
$uniqueConstraint = array('columns' => $uniqueConstraintAnnot->columns);
if ( ! empty($uniqueConstraintAnnot->name)) {
$primaryTable['uniqueConstraints'][$uniqueConstraintAnnot->name] = $uniqueConstraint;
} else {
$primaryTable['uniqueConstraints'][] = $uniqueConstraint;
}
}
}
$metadata->setPrimaryTable($primaryTable);
}
// Evaluate NamedQueries annotation
if (isset($classAnnotations['Doctrine\ORM\Mapping\NamedQueries'])) {
$namedQueriesAnnot = $classAnnotations['Doctrine\ORM\Mapping\NamedQueries'];
if (!is_array($namedQueriesAnnot->value)) {
throw new \UnexpectedValueException("@NamedQueries should contain an array of @NamedQuery annotations.");
}
foreach ($namedQueriesAnnot->value as $namedQuery) {
if (!($namedQuery instanceof \Doctrine\ORM\Mapping\NamedQuery)) {
throw new \UnexpectedValueException("@NamedQueries should contain an array of @NamedQuery annotations.");
}
$metadata->addNamedQuery(array(
'name' => $namedQuery->name,
'query' => $namedQuery->query
));
}
}
// Evaluate InheritanceType annotation
if (isset($classAnnotations['Doctrine\ORM\Mapping\InheritanceType'])) {
$inheritanceTypeAnnot = $classAnnotations['Doctrine\ORM\Mapping\InheritanceType'];
$metadata->setInheritanceType(constant('Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_' . $inheritanceTypeAnnot->value));
if ($metadata->inheritanceType != \Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_NONE) {
// Evaluate DiscriminatorColumn annotation
if (isset($classAnnotations['Doctrine\ORM\Mapping\DiscriminatorColumn'])) {
$discrColumnAnnot = $classAnnotations['Doctrine\ORM\Mapping\DiscriminatorColumn'];
$metadata->setDiscriminatorColumn(array(
'name' => $discrColumnAnnot->name,
'type' => $discrColumnAnnot->type,
'length' => $discrColumnAnnot->length
));
} else {
$metadata->setDiscriminatorColumn(array('name' => 'dtype', 'type' => 'string', 'length' => 255));
}
// Evaluate DiscriminatorMap annotation
if (isset($classAnnotations['Doctrine\ORM\Mapping\DiscriminatorMap'])) {
$discrMapAnnot = $classAnnotations['Doctrine\ORM\Mapping\DiscriminatorMap'];
$metadata->setDiscriminatorMap($discrMapAnnot->value);
}
}
}
// Evaluate DoctrineChangeTrackingPolicy annotation
if (isset($classAnnotations['Doctrine\ORM\Mapping\ChangeTrackingPolicy'])) {
$changeTrackingAnnot = $classAnnotations['Doctrine\ORM\Mapping\ChangeTrackingPolicy'];
$metadata->setChangeTrackingPolicy(constant('Doctrine\ORM\Mapping\ClassMetadata::CHANGETRACKING_' . $changeTrackingAnnot->value));
}
// Evaluate annotations on properties/fields
foreach ($class->getProperties() as $property) {
if ($metadata->isMappedSuperclass && ! $property->isPrivate()
||
$metadata->isInheritedField($property->name)
||
$metadata->isInheritedAssociation($property->name)) {
continue;
}
$mapping = array();
$mapping['fieldName'] = $property->getName();
// Check for JoinColummn/JoinColumns annotations
$joinColumns = array();
if ($joinColumnAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinColumn')) {
$joinColumns[] = array(
'name' => $joinColumnAnnot->name,
'referencedColumnName' => $joinColumnAnnot->referencedColumnName,
'unique' => $joinColumnAnnot->unique,
'nullable' => $joinColumnAnnot->nullable,
'onDelete' => $joinColumnAnnot->onDelete,
'columnDefinition' => $joinColumnAnnot->columnDefinition,
);
} else if ($joinColumnsAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinColumns')) {
foreach ($joinColumnsAnnot->value as $joinColumn) {
$joinColumns[] = array(
'name' => $joinColumn->name,
'referencedColumnName' => $joinColumn->referencedColumnName,
'unique' => $joinColumn->unique,
'nullable' => $joinColumn->nullable,
'onDelete' => $joinColumn->onDelete,
'columnDefinition' => $joinColumn->columnDefinition,
);
}
}
// Field can only be annotated with one of:
// @Column, @OneToOne, @OneToMany, @ManyToOne, @ManyToMany
if ($columnAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Column')) {
if ($columnAnnot->type == null) {
throw MappingException::propertyTypeIsRequired($className, $property->getName());
}
$mapping['type'] = $columnAnnot->type;
$mapping['length'] = $columnAnnot->length;
$mapping['precision'] = $columnAnnot->precision;
$mapping['scale'] = $columnAnnot->scale;
$mapping['nullable'] = $columnAnnot->nullable;
$mapping['unique'] = $columnAnnot->unique;
if ($columnAnnot->options) {
$mapping['options'] = $columnAnnot->options;
}
if (isset($columnAnnot->name)) {
$mapping['columnName'] = $columnAnnot->name;
}
if (isset($columnAnnot->columnDefinition)) {
$mapping['columnDefinition'] = $columnAnnot->columnDefinition;
}
if ($idAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Id')) {
$mapping['id'] = true;
}
if ($generatedValueAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\GeneratedValue')) {
$metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_' . $generatedValueAnnot->strategy));
}
if ($versionAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Version')) {
$metadata->setVersionMapping($mapping);
}
$metadata->mapField($mapping);
// Check for SequenceGenerator/TableGenerator definition
if ($seqGeneratorAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\SequenceGenerator')) {
$metadata->setSequenceGeneratorDefinition(array(
'sequenceName' => $seqGeneratorAnnot->sequenceName,
'allocationSize' => $seqGeneratorAnnot->allocationSize,
'initialValue' => $seqGeneratorAnnot->initialValue
));
} else if ($tblGeneratorAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\TableGenerator')) {
throw MappingException::tableIdGeneratorNotImplemented($className);
}
} else if ($oneToOneAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OneToOne')) {
if ($idAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Id')) {
$mapping['id'] = true;
}
$mapping['targetEntity'] = $oneToOneAnnot->targetEntity;
$mapping['joinColumns'] = $joinColumns;
$mapping['mappedBy'] = $oneToOneAnnot->mappedBy;
$mapping['inversedBy'] = $oneToOneAnnot->inversedBy;
$mapping['cascade'] = $oneToOneAnnot->cascade;
$mapping['orphanRemoval'] = $oneToOneAnnot->orphanRemoval;
$mapping['fetch'] = $this->getFetchMode($className, $oneToOneAnnot->fetch);
$metadata->mapOneToOne($mapping);
} else if ($oneToManyAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OneToMany')) {
$mapping['mappedBy'] = $oneToManyAnnot->mappedBy;
$mapping['targetEntity'] = $oneToManyAnnot->targetEntity;
$mapping['cascade'] = $oneToManyAnnot->cascade;
$mapping['indexBy'] = $oneToManyAnnot->indexBy;
$mapping['orphanRemoval'] = $oneToManyAnnot->orphanRemoval;
$mapping['fetch'] = $this->getFetchMode($className, $oneToManyAnnot->fetch);
if ($orderByAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OrderBy')) {
$mapping['orderBy'] = $orderByAnnot->value;
}
$metadata->mapOneToMany($mapping);
} else if ($manyToOneAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\ManyToOne')) {
if ($idAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Id')) {
$mapping['id'] = true;
}
$mapping['joinColumns'] = $joinColumns;
$mapping['cascade'] = $manyToOneAnnot->cascade;
$mapping['inversedBy'] = $manyToOneAnnot->inversedBy;
$mapping['targetEntity'] = $manyToOneAnnot->targetEntity;
$mapping['fetch'] = $this->getFetchMode($className, $manyToOneAnnot->fetch);
$metadata->mapManyToOne($mapping);
} else if ($manyToManyAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\ManyToMany')) {
$joinTable = array();
if ($joinTableAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinTable')) {
$joinTable = array(
'name' => $joinTableAnnot->name,
'schema' => $joinTableAnnot->schema
);
foreach ($joinTableAnnot->joinColumns as $joinColumn) {
$joinTable['joinColumns'][] = array(
'name' => $joinColumn->name,
'referencedColumnName' => $joinColumn->referencedColumnName,
'unique' => $joinColumn->unique,
'nullable' => $joinColumn->nullable,
'onDelete' => $joinColumn->onDelete,
'columnDefinition' => $joinColumn->columnDefinition,
);
}
foreach ($joinTableAnnot->inverseJoinColumns as $joinColumn) {
$joinTable['inverseJoinColumns'][] = array(
'name' => $joinColumn->name,
'referencedColumnName' => $joinColumn->referencedColumnName,
'unique' => $joinColumn->unique,
'nullable' => $joinColumn->nullable,
'onDelete' => $joinColumn->onDelete,
'columnDefinition' => $joinColumn->columnDefinition,
);
}
}
$mapping['joinTable'] = $joinTable;
$mapping['targetEntity'] = $manyToManyAnnot->targetEntity;
$mapping['mappedBy'] = $manyToManyAnnot->mappedBy;
$mapping['inversedBy'] = $manyToManyAnnot->inversedBy;
$mapping['cascade'] = $manyToManyAnnot->cascade;
$mapping['indexBy'] = $manyToManyAnnot->indexBy;
$mapping['orphanRemoval'] = $manyToManyAnnot->orphanRemoval;
$mapping['fetch'] = $this->getFetchMode($className, $manyToManyAnnot->fetch);
if ($orderByAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OrderBy')) {
$mapping['orderBy'] = $orderByAnnot->value;
}
$metadata->mapManyToMany($mapping);
}
}
// Evaluate @HasLifecycleCallbacks annotation
if (isset($classAnnotations['Doctrine\ORM\Mapping\HasLifecycleCallbacks'])) {
foreach ($class->getMethods() as $method) {
// filter for the declaring class only, callbacks from parents will already be registered.
if ($method->isPublic() && $method->getDeclaringClass()->getName() == $class->name) {
$annotations = $this->_reader->getMethodAnnotations($method);
if ($annotations && is_numeric(key($annotations))) {
foreach ($annotations as $annot) {
$annotations[get_class($annot)] = $annot;
}
}
if (isset($annotations['Doctrine\ORM\Mapping\PrePersist'])) {
$metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::prePersist);
}
if (isset($annotations['Doctrine\ORM\Mapping\PostPersist'])) {
$metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::postPersist);
}
if (isset($annotations['Doctrine\ORM\Mapping\PreUpdate'])) {
$metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::preUpdate);
}
if (isset($annotations['Doctrine\ORM\Mapping\PostUpdate'])) {
$metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::postUpdate);
}
if (isset($annotations['Doctrine\ORM\Mapping\PreRemove'])) {
$metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::preRemove);
}
if (isset($annotations['Doctrine\ORM\Mapping\PostRemove'])) {
$metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::postRemove);
}
if (isset($annotations['Doctrine\ORM\Mapping\PostLoad'])) {
$metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::postLoad);
}
if (isset($annotations['Doctrine\ORM\Mapping\PreFlush'])) {
$metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::preFlush);
}
}
}
}
}
SOLUTION
Problem was with AnnotationReader which I forgot to set in /config/config.php.
The final /config/config.php is as following
<?php
use Doctrine\Common\ClassLoader,
Doctrine\ORM\Configuration,
Doctrine\ORM\EntityManager,
Doctrine\Common\Cache\ArrayCache,
Doctrine\Common\Annotations\AnnotationReader,
Doctrine\ORM\Mapping\Driver\AnnotationDriver,
Doctrine\DBAL\Logging\EchoSqlLogger,
Doctrine\DBAL\Event\Listeners\MysqlSessionInit,
Doctrine\ORM\Tools\SchemaTool,
Doctrine\ORM\Tools\Setup,
Doctrine\Common\EventManager,
Gedmo\Timestampable\TimestampableListener,
Gedmo\Sluggable\SluggableListener,
Gedmo\Tree\TreeListener,
Gedmo\SoftDeleteable\SoftDeleteableListener,
Gedmo\Loggable\LoggableListener;
include_once(dirname(__FILE__) . '/database.php');
include_once 'app/thirdparty/Doctrine/Common/ClassLoader.php';
include_once 'app/thirdparty/Doctrine/ORM/Tools/Setup.php';
$APP_NAME = "TGCore";
if($_SERVER['HTTP_HOST'] == "localhost"){
$_CONFIG['base_url'] = "http://localhost/{$APP_NAME}/";
$_CONFIG['base_path'] = $_SERVER['DOCUMENT_ROOT'] . "/{$APP_NAME}/";
}else{
$_CONFIG['base_url'] = "http://localhost/{$APP_NAME}/";
$_CONFIG['base_path'] = $_SERVER['DOCUMENT_ROOT'] . "/{$APP_NAME}/";
}
define('ROOT_HOST', $_CONFIG['base_url']);
define('ROOT_DIR', $_CONFIG['base_path']);
/*********** Define the values *********/
define("HOSTNAME", $db['hostname']);
define("USERNAME", $db['username']);
define("PASSWORD", $db['password']);
define("DATABASE", $db['database']);
define("BASE_URL", ROOT_HOST);
$application_folder = 'app';
define('APPPATH', ROOT_DIR.$application_folder.'/');
define('EXT', '.php');
/**
*
* @var Doctrine\ORM\EntityManager
*/
$em = null;
/*bootstrapping doctrine*/
// Set up class loading
$doctrineClassLoader = new ClassLoader('Doctrine', APPPATH.'thirdparty');
$doctrineClassLoader->register();
// Set up Gedmo
$classLoader = new ClassLoader('Gedmo', APPPATH.'thirdparty');
$classLoader->register();
// Set up zamoon extensions
$zExtensionsLoader = new ClassLoader('z', APPPATH.'thirdparty');
$zExtensionsLoader->register();
// Set up models loading
$entitiesClassLoader = new ClassLoader('models', APPPATH);
$entitiesClassLoader->register();
$isDevMode = true;
$proxiesClassLoader = new ClassLoader('Proxies', APPPATH.'models/proxies');
$proxiesClassLoader->register();
$ormConfig = new Doctrine\ORM\Configuration;
/*************************************** 1 ******************************************/
//print ("ensure standard doctrine annotations are registered<br/>");
Doctrine\Common\Annotations\AnnotationRegistry::registerFile(APPPATH.'thirdparty/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php');
/*************************************** 2 ******************************************/
// print("Set up caches<br/>");
$arrayCache = new Doctrine\Common\Cache\ArrayCache;
$annotationReader = new Doctrine\Common\Annotations\AnnotationReader;
$cachedAnnotationReader = new Doctrine\Common\Annotations\CachedReader(
$annotationReader, // use reader
$arrayCache // and a cacheDriver
);
/*************************************** 3 ******************************************/
// 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
);
/*************************************** 4 ******************************************/
// 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
array(APPPATH.'models/') // paths to look in
);
/*************************************** 5 ******************************************/
// NOTE: driver for application Entity can be different, Yaml, Xml or whatever
// register annotation driver for our application Entity namespace
$driverChain->addDriver($annotationDriver, 'models');
/*************************************** 6 ******************************************/
// print("ORM Proxy configuration");
$ormConfig->setProxyDir(APPPATH.'/models/proxies');
$ormConfig->setProxyNamespace('Proxies');
$ormConfig->setAutoGenerateProxyClasses(TRUE); // this can be based on production config.
// register metadata driver
$ormConfig->setMetadataDriverImpl($driverChain);
// use our allready initialized cache driver
$ormConfig->setMetadataCacheImpl($arrayCache);
$ormConfig->setQueryCacheImpl($arrayCache);
//$driverImpl = $ormConfig->newDefaultAnnotationDriver(array(APPPATH.'models/'));
/*************************************** 7 ******************************************/
$evm = new Doctrine\Common\EventManager();
//print("gedmo extension listeners");
// 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);
//loggable
$loggableListener = new Gedmo\Loggable\LoggableListener;
$loggableListener->setAnnotationReader($cachedAnnotationReader);
$evm->addEventSubscriber($loggableListener);
// timestampable
$timestampableListener = new Gedmo\Timestampable\TimestampableListener;
$timestampableListener->setAnnotationReader($cachedAnnotationReader);
$evm->addEventSubscriber($timestampableListener);
//soft delete
$softdeletelistener = new Gedmo\SoftDeleteable\SoftDeleteableListener;
$softdeletelistener->setAnnotationReader($cachedAnnotationReader);
$evm->addEventSubscriber($softdeletelistener);
//setup soft delete filter
$ormConfig->addFilter('soft-deleteable', 'Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter');
// Database connection information
$connectionOptions = array(
'driver' => 'pdo_mysql',
'user' => "root",
'password' => "mysql",
'host' => "localhost",
'dbname' => "TG"
);
//central access point to ORM functionality.
$em = EntityManager::create($connectionOptions, $ormConfig, $evm);
//create/drop/update database schemas based on <tt>ClassMetadata</tt> class descriptors.
$tool = new SchemaTool($em);
if($em){
//ORM metadata descriptor for a class.
$schemas = array( $em->getClassMetadata('models\Country')
);
}
//Create the databaseschema for the given array of ClassMetadata instances.
$tool->createSchema($schemas);
/* End of file config.php */
/* Location: ./appl/config/config.php */
REFERENCES
1 - Integrating Doctrine 2 with CodeIgniter 2, available at http://wildlyinaccurate.com/integrating-doctrine-2-with-codeigniter-2
2 - Setting up CodeIgniter 2 with Doctrine 2 the right way, available at http://www.joelverhagen.com/blog/2011/05/setting-up-codeigniter-2-with-doctrine-2-the-right-way/
3 - CodeIgniter-2-with-Doctrine-2, available at https://github.com/iPrayag/CodeIgniter-2-with-Doctrine-2/blob/master/application/libraries/Doctrine.php
4 - Using Doctrine with Code Igniter, available https://github.com/EllisLab/CodeIgniter/wiki/Using-Doctrine-with-Code-Igniter
5- Integrating with CodeIgniter, available at http://docs.doctrine-project.org/en/2.1/cookbook/integrating-with-codeigniter.html
6 - CodeIgniter 2 Doctrine 2 Integration, available at http://searchdaily.net/codeigniter-2-doctrine-2-integration/
No comments:
Post a Comment