I'm trying to learn about using Doctrine 2 by making a very simple script which fetches information from my database. The problem is that I can't find any documentation explaining how Doctrine finds and uses my mapping entities. And so when it complains that it's not finding an entity, I don't know what to do to solve the problem. Consider the following structure in my www folder:
Doctrine/
Entities/
person.php
myTestPage.php
person.php
<?php
/** #Entity #Table(name="person")*/
class person
{
/**
* #Id #Column(type="integer")
*/
protected $uid;
}
?>
myTestPage.php
<?php
require "Doctrine/Doctrine/ORM/Tools/Setup.php";
$lib = "Doctrine";
Doctrine\ORM\Tools\Setup::registerAutoloadDirectory($lib);
use Doctrine\ORM\Tools\Setup,
Doctrine\ORM\EntityManager;
$paths = array("/Entities");
$isDevMode = true;
$dbParams = array("driver" => "pdo_mysql",
"host" => "myhost.ca",
"user" => "Shawn",
"password" => "noneofyourbusiness",
"dbname" => "testDB");
$config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);
$em = EntityManager::create($dbParams, $config);
$qb = $em->createQueryBuilder();
$qb->select(array('uid'))
->from('person', 't');
$query = $qb->getQuery();
$result = $query->getResult();
echo $result;
?>
When I visit myTestPage.php, I get the following error message:
Fatal error: Uncaught exception 'Doctrine\ORM\Query\QueryException'
with message '[Semantical Error] line 0, col 24 near 'person':
Error: Class 'person' is not defined.' in
C:\wamp\www\Doctrine\Doctrine\ORM\Query\QueryException.php on line 47
The problem seems to be that Doctrine can't find person.php, but how can I solve this?
I don't exactly know what the "re1_chercheur" means, but when I tried your code, it complained about person not being defined, so i included that and it worked.
Of course, this should be dealt with by using an autoloader of some sort, but I think doctrine has some solution for that also. I haven't been using their autoloader, because I have my own which uses the PSR compliant autoloading.
Also in your select, if you want just the "uid", use "t.uid". "t" is the alias of the person class, so in other places in the query, you'll be using "t" to get to it's properties (you could do a ->where("t.uid = someNumber")). If you want the whole object use select("t");
I found the doctrine documentation quite helpful, just make sure you go in the order it is laid out, and you'll get the hang of it in no time.
I know this is not an exact answer, but maybe it points you into the right direction.
Related
I am new to doctrine(using version 1.2) and following the steps given in the documentation manual. I've installed and configured it perfectly. But i have a problem while working with models. I have followed each and every step and have successfully generated the models in the models folder.. but after that when i m using the demo code
$user = new User();
$user->username = 'jwage';
$user->password = 'changeme';
it says..
Fatal error: Class 'User' not found in C:\wamp\www\test_doctrine\test.php on line 25
whilst if i check the output of
Doctrine_Core::loadModels('models');
i get
Array
(
[BaseUser] => BaseUser
[User] => User
[UserTable] => UserTable
)
how do i get access to the User class??
Doctrine is not loading the base classes. I had faced a similar problem and I solved it by modifying the autoload function wherein I am getting the base class and I require them then and there itself.
You then in the bootstrap.php file, after spl_autoload_register(array('Doctrine', 'autoload'));, you need to Doctrine_Core::loadModels('models');.
This way the base class gets included through the autoload function and the child class (in this case the User Class) can extend it and then you can access it.
I've been looking for an explanation on how to integrate Doctrine 2 and Zend Framework 1.12 (or 1.11, or another --I don't really know whether it matters or not but what I'm using is 1.12). I could find several blog posts and even solved questions right here in Stack Overflow but after read them one and all, I couldn't get to get what I was after: do it in a modular application. So, I'd be very grateful if somebody could give me the keys to achieve this.
Thank you very much!
EDIT:
Thank you guys for your replies but the recent release of ZF2 made me to decide to leave ZF1 in order to take advantage of all new improvements and features. As #KTastrophy said, integrating ZF and Doctrine is quite much easier now (I'd even dare to say that everything is easier and more consistent with ZF2). Thank you one more time!
It's easy to integrate doctrine 2 with ZF using the doctrine PEAR installation. After installing you just need to put this in your bootstrap:
protected function _initDoctrine() {
require_once "Doctrine/ORM/Tools/Setup.php";
\Doctrine\ORM\Tools\Setup::registerAutoloadPEAR();
$options = $this->getOptions();
$loader = new \Doctrine\Common\ClassLoader('YourNamespace', realpath(APPLICATION_PATH . "/../library"));
$loader->register();
$isDevMode = (APPLICATION_ENV == 'production') ? false: true;
$entityManager = \Doctrine\ORM\EntityManager::create(
$options['doctrine']['dbal'],
\Doctrine\ORM\Tools\Setup::createYAMLMetadataConfiguration(array(
realpath(APPLICATION_PATH."/../library/YourNamespace/Yaml"),
), $isDevMode)
);
Zend_Registry::set('entityManager', $entityManager);
return $entityManager;
}
The $this->getOptions() retrieves the database name, user and password from the config file.
If you take this tutorial as an example
http://christian.soronellas.es/2010/12/19/zend-framework-and-doctrine-2/?lang=en
See this part of the configuration code
$config = new Configuration();
$config -> setMetadataCacheImpl($cache);
$driverImpl = $config -> newDefaultAnnotationDriver($options['entitiesPath']);
$config -> setMetadataDriverImpl($driverImpl);
$config -> setQueryCacheImpl($cache);
$config -> setProxyDir($options['proxiesPath']);
$config -> setProxyNamespace('Application\Models\Proxies');
$config -> setAutoGenerateProxyClasses(('development' == APPLICATION_ENV));
$em = EntityManager::create( $this -> _buildConnectionOptions($options), $config );
The function newDefaultAnnotationDriver actually takes an array of entitites path. This creates the opportunity for you to get creative. When I found out about this, I simply created an entity folder in each module and pass each path along the newDefaultAnnotationDriver parameter in an array. Ofcourse by doing this, you will need to set the namespace per module.
I use Bisna
You should apply this patch https://github.com/guilhermeblanco/ZendFramework1-Doctrine2/pull/45
And that works well for me.
In the controller I have this function for retrieve the Entity Manager
/**
* Retrieve the Doctrine Container.
*
* #return Doctrine\ORM\EntityManager
*/
public function getEntityManager()
{
return $this->getInvokeArg('bootstrap')->getResource('doctrine')->getEntityManager();
}
I'm converting an old PHP project to the Symfony2 framework. Some of the pages are now handled by my Symfony2 front controller (index.php), but many pages have not yet been converted.
The problem is that, within Symfony, all of my Doctrine entity annotations must begin with the ORM\ prefix, but outside of Symfony, that prefix does not appear to be enabled, and so I get the following error:
Class MyProject\MyBundle\Entity\MyClass is not a valid entity or mapped super class.
I've tried to duplicate whatever magic Symfony does to set this up, including following these instructions [doctrine-project.org], and actually including app/autoload.php entirely into my legacy bootstrap process. But nothing works.
Does anyone know how I can manually replicate whatever it is that Symfony does to enable the ORM\ prefix for my Doctrine annotations?
I got the answer from the Symfony2 Google group. The problem is that the Doctrine configuration shown in the documentation uses SimpleAnnotationReader behind the scenes, but you need regular AnnotationReader to use the ORM\ namespace prefix. I got it to work by replacing this:
$config = new Doctrine\ORM\Configuration();
$driver = $config->newDefaultAnnotationDriver('/path/to/my/entities');
with this:
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
// ...
$config = new Doctrine\ORM\Configuration();
$reader = new AnnotationReader();
$driver = new AnnotationDriver($reader, '/path/to/my/entities');
I ended up with:
Doctrine\ORM\Tools\Setup::createAnnotationMetadataConfiguration($paths, $devMode, null, null, false);`
The 3rd and 4th null arguments are default. The 5th false argument tells it to make a standard AnnotationReader rather than a basic one.
I'm using Doctrine 2.5.6.
Explanation
I found I couldn't get Ian's solution working without calling Doctrine\ORM\Tools\Setup::createAnnotationMetadataConfiguration before making my own config. I was getting this error:
'[Semantical Error] The annotation "#Doctrine\ORM\Mapping\Entity" in class My\Class does not exist, or could not be auto-loaded.'
I was really confused so I took a look at the source code.
It turns out createAnnotationMetadataConfiguration calls Doctrine\ORM\Configuration::newDefaultAnnotationDriver rather than creating the annotation driver directly. This calls AnnotationRegistry::registerFile(__DIR__ . '/Mapping/Driver/DoctrineAnnotations.php'); which seems to be critical. After that, newDefaultAnnotationDriver just creates a new AnnotationDriver().
i setup Doctrine 1 b4 but it seems like now when i try Doctrine 2 it fails
i have Doctrine installed at D:\ResourceLibrary\Frameworks\Doctrine
D:\ResourceLibrary\Frameworks\Doctrine\bin
D:\ResourceLibrary\Frameworks\Doctrine\Doctrine
D:\ResourceLibrary\Frameworks\Doctrine\Doctrine\Common
D:\ResourceLibrary\Frameworks\Doctrine\Doctrine\DBAL
D:\ResourceLibrary\Frameworks\Doctrine\Doctrine\ORM
i put D:\ResourceLibrary\Frameworks\Doctrine\bin in the PATH Windows Environment Variable
and added D:\ResourceLibrary\Frameworks\Doctrine to the php.ini include_path
i find that when i try to do
D:\>php doctrine.php
Could not open input file: doctrine.php
fails ... i thought that since i have D:\ResourceLibrary\Frameworks\Doctrine\bin in the PATH Windows Environment Variable, it shld be able to find doctrine.php?
D:\ResourceLibrary\Frameworks\Doctrine\bin>php doctrine.php
Warning: require(D:\ResourceLibrary\Frameworks\Doctrine\bin/../lib/vendor\Symfony\Components\Console\Helper\HelperSet.ph
p): failed to open stream: No such file or directory in D:\ResourceLibrary\Frameworks\Doctrine\Doctrine\Common\ClassLoad
er.php on line 143
Fatal error: require(): Failed opening required 'D:\ResourceLibrary\Frameworks\Doctrine\bin/../lib/vendor\Symfony\Compon
ents\Console\Helper\HelperSet.php' (include_path='D:\ResourceLibrary\Frameworks\ZendFramework\library;D:\ResourceLibrary
\Frameworks\Doctrine;.;c:\php\includes') in D:\ResourceLibrary\Frameworks\Doctrine\Doctrine\Common\ClassLoader.php on li
ne 143
then 2nd try, pass with errors ...
After spending several hours to configure Doctrine 2 on my machine last night I finally succedded to work with Doctrine 2.
I configured Doctrine 2 in this way.
There are several ways to install Doctrine 2 although I preferred to download from package manager.
First I downloaded package DoctrineORM-2.0.0BETA3.tgz from http://www.doctrine-project.org/projects/orm/download
I extracted the tar file inside my test folder where I tested my sample code. My folder looks like
./test
DoctrineORM/
DoctrineORM/bin
DoctrineORM/bin/Doctrine
Then I created 2 folders on root 'model' and 'proxies'.
Now we need to bootstrap Doctrine.
--- Bootsrap ---
<?php
// test.php
require 'DoctrineORM/Doctrine/Common/ClassLoader.php';
$classLoader = new \Doctrine\Common\ClassLoader('Doctrine', 'DoctrineORM');
$classLoader->register(); // register on SPL autoload stack
$classloader = new \Doctrine\Common\ClassLoader('model', __DIR__);
$classloader->register();
$config = new \Doctrine\ORM\Configuration();
$cache = new \Doctrine\Common\Cache\ArrayCache();
$config->setMetadataCacheImpl($cache);
$config->setQueryCacheImpl($cache);
$driverImpl = $config->newDefaultAnnotationDriver('model');
$config->setMetadataDriverImpl($driverImpl);
$config->setProxyDir('proxies');
$config->setProxyNamespace('proxies');
$config->setAutoGenerateProxyClasses(true);
$config->getAutoGenerateProxyClasses();
$connectionOptions = array(
'driver' => 'pdo_mysql',
'dbname' => 'test',
'user' => '[DB_User]',
'password' => '[DB_Pass]'
);
$em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config);
//echo 'Hello World!' . PHP_EOL;
// Get result from Table
$q = $em->createQuery('SELECT c FROM model\User c ORDER BY c.name');
$t = $q->getResult();
echo "<pre>"; print_r($t);
// Save a new User to DB
$uu = new model\User();
$uu->name = 'test name1';
$uu->age = 4;
$em->persist($uu);
$em->flush();
--- Bootsrap ---
Then I created a model file in model directory
--- Model - User.php ---
<?php
// Model File model/User.php
namespace Model;
/** #Entity #Table(name="users") */
class User
{
/**
* #Id #Column(type="integer")
* #GeneratedValue(strategy="AUTO")
*/
public $id;
/** #Column(type="string", length=50) */
public $name;
/** #Column(type="integer", length=50) */
public $age;
}
--- Model - User.php ---
My complete folder structure now looks like below.
./test
DoctrineORM/
DoctrineORM/bin
DoctrineORM/bin/Doctrine
Model/
Model/User.php
test.php
Hope this will help you. If you need any further help I can send you the complete source which works fine at my machine.
You don't need the entire Symfony framework. Just the bits that Doctrine relies on.
If you download the current version of the ORM component (right now at BETA2), it will include a folder called Symfony (probably in lib/vendor/Symfony, but it tends to move around with new releases). You need to make sure that the ClassLoader in doctrine.php or cli-config.php can find that Symfony folder.
$classLoader = new \Doctrine\Common\ClassLoader('Symfony', __DIR__ . '/path/to/Symfony');
$classLoader->register();
I hope this information is accurate. The Doctrine team keeps messing with the structure of the release they closer they get to a final version.
If you want to use the command line interface in the new Doctrine 2 beta you also have to install the Symfony 2 framework (because it includes the Console Helper) and put it into your include path.
As far as I know there is currently no PEAR installation available, so you will have to download the sources from the Symfony 2 website or via Git.
On a sidenote: It seems that you also tried to execute doctrine.php at a path where it doesn’t exist. That’s the reason why you got the
Could not open input file: doctrine.php
error message.
Doctrine v2.* is stored in bin dir.
Try like this :
$ vendor/bin/doctrine orm:conver-mapping xml src/ --from-database --force
Dont put PHP on start.
i just started using PHP namespaces. I have two models classes in separate files
In both files first i declare namespace
namespace eu\ed\sixImport\importViewer\models;
first class:
class Log extends \Doctrine_Record
$this->hasMany('eu\ed\sixImport\importViewer\models\DataSource as DataSource', array(
'local' => 'id',
'foreign' => 'logId'));//setup relationship in setUp method
second class:
class DataSource extends \Doctrine_Record
$this->hasOne('eu\ed\sixImport\importViewer\models\Log as Log', array(
'local' => 'logId',
'foreign' => 'id'));//setup relationship in setUp method
Everything works fine untill i make something like this
$query = \Doctrine_Query::create()
->select('log.*')
->from('eu\ed\sixImport\importViewer\models\Log log')
->leftJoin("log.DataSource")
->orderBy("log.id DESC");
$requiredPage = (($startingRow - ($startingRow%$rowsRequired))/$rowsRequired) + 1;
$pager = new \Doctrine_Pager($query, $requiredPage, $rowsRequired);
$res = $pager->execute();
$this->logsPageCount = $pager->getNumResults();
print_r($res[0]["DataSource"]->toArray());//it fails on access to relationship
Than Doctrine throw Exception
Uncaught exception 'Doctrine_Exception' with message 'Couldn't find class eu\ed' in C:\wamp\www\importViewer\resources\doctrine\Doctrine-1.1.5\lib\Doctrine\Table.php:293...
From Exception, you can see, it looks for class 'eu\ed'. Backslash[s] cut the rest of the class name, and than class is not obviously found. Can you give me some suggestion, how to solve this problem?
Thanks
I am not sure if Doctrine 1 supports namespaces. I really recommend using Doctrine 2 - it is built on top of mature architecture (with API from Java Hibernate) and does not involve that much magic like Doctrine 1.