I have already discussed few articles on codeigniter along with codeigniter basics. Codeigniter has good library/mechanism for manipulating database activity. Besides, it introduced active record class, which minimizes the complexity of writing SQL query. However, database support in codeigniter isn’t still good enough for many. Specially, many developers prefer to work with ORM for database layer and CodeIgniter doesn’t provide such built-in support. However, doctrine is a very powerful ORM in php and it is possible to easily integrate and use doctrine with CodeIgniter as ORM.
There is an official help page to do so, On official documentation page. However, you might get some issues and can’t understand why those are appearing clearly, specially as a beginner, same happened to me. That’s why, i think a more detailed explanation may help you in the way. So, In this tutorial, i will show how can we integrate this doctrine with CodeIgniter. This will follow will show some basic usage with PHO code examples. I am assuming, you have some basic knowledge in CodeIgniter. Basic understanding about what doctrine is and how it works, are also needed. You can follow an official getting started with doctrine tutorial.
Download And Install:
First, please download the latest doctrine orm. Now extract the contents and copy the extracted ‘doctrine’ directory to your CodeIgniter application’s ‘third_party’ directory.
Alternatively, if you are a composer fan, and already using composer with codeigniter, you can install doctrine orm via adding dependency on composer.json as below:
"require": { "doctrine/orm": "dev-master" }
Now, in ‘application/libraries’ directory, lets create a new class file named ‘doctrine.php’ that will include all initialization of our doctrine library for our CodeIgniter application. The class is as follows:
use Doctrine\Common\ClassLoader, Doctrine\ORM\Configuration, Doctrine\ORM\EntityManager, Doctrine\Common\Cache\ArrayCache, Doctrine\DBAL\Logging\EchoSQLLogger, Doctrine\ORM\Mapping\Driver\DatabaseDriver, Doctrine\ORM\Tools\DisconnectedClassMetadataFactory, Doctrine\ORM\Tools\EntityGenerator; /** * CodeIgniter Smarty Class * * initializes basic doctrine settings and act as doctrine object * * @final Doctrine * @category Libraries * @author Md. Ali Ahsan Rana * @link https://codesamplez.com/ */ class Doctrine { /** * @var EntityManager $em */ public $em = null; /** * constructor */ public function __construct() { // load database configuration from CodeIgniter require APPPATH.'config/database.php'; // Set up class loading. You could use different autoloaders, provided by your favorite framework, // if you want to. require_once APPPATH.'third_party/Doctrine/Common/ClassLoader.php'; $doctrineClassLoader = new ClassLoader('Doctrine', APPPATH.'third_party'); $doctrineClassLoader->register(); $entitiesClassLoader = new ClassLoader('models', rtrim(APPPATH, "/" )); $entitiesClassLoader->register(); $proxiesClassLoader = new ClassLoader('proxies', APPPATH.'models'); $proxiesClassLoader->register(); // Set up caches $config = new Configuration; $cache = new ArrayCache; $config->setMetadataCacheImpl($cache); $driverImpl = $config->newDefaultAnnotationDriver(array(APPPATH.'models/Entities')); $config->setMetadataDriverImpl($driverImpl); $config->setQueryCacheImpl($cache); // Proxy configuration $config->setProxyDir(APPPATH.'models/proxies'); $config->setProxyNamespace('Proxies'); // Set up logger //$logger = new EchoSQLLogger; //$config->setSQLLogger($logger); $config->setAutoGenerateProxyClasses( TRUE ); // Database connection information $connectionOptions = array( 'driver' => 'pdo_mysql', 'user' => $db['default']['username'], 'password' => $db['default']['password'], 'host' => $db['default']['hostname'], 'dbname' => $db['default']['database'] ); // Create EntityManager $this->em = EntityManager::create($connectionOptions, $config); } }
NOTE: This above code requires php 5.3.x version installed on your server.
The above class is almost same as the one described on official reference, just optimized to be usable on codeigniter 2.x versions. Also, you will need to create two directories inside the ‘application/models’ directory, named ‘proxies’ and ‘entities’. On the above code, first we loaded codeigniter’s database configuration and doctrine class loaded to load necessary classes. Then it loads some necessary items. To know more in details about the configuration options and know how they works, please refer to official documentation of doctrine configuration options reference.
Read The Complete CodeIgniter Tutorials Series By CodeSamplez.com
Create Entity From Database Automatically:
Although, its possible to generate entity classes from YAML file/ database through some command line argument, its much easier to have them generated right from the PHP script without any kind of extra effort. Following is an extra function that will help you to generate the entity classes. Just put it within the previously given class and call it at the last line on class constructor.
/** * generate entity objects automatically from mysql db tables * @return none */ function generate_classes(){ $this->em->getConfiguration() ->setMetadataDriverImpl( new DatabaseDriver( $this->em->getConnection()->getSchemaManager() ) ); $cmf = new DisconnectedClassMetadataFactory(); $cmf->setEntityManager($this->em); $metadata = $cmf->getAllMetadata(); $generator = new EntityGenerator(); $generator->setUpdateEntityIfExists(true); $generator->setGenerateStubMethods(true); $generator->setGenerateAnnotations(true); $generator->generate($metadata, APPPATH."models/Entities"); }
Remember, activate calling to this method only once. and then after the entity classes are generated, keep it commented, otherwise you may get errors. If sometime, database structure changes/tables added/removed, just clear the ‘entities’ directory and reactivate the method(one time only, as well).
Basic Usage Of Doctrine With CodeIgniter:
Lets do a contact form example to understand how to use doctrine ORM within CodeIgniter. Lets create a table on our MySQL database named ‘pd_contact’ as like follows:
This will generate and entity class as like follows:
<?php /** * PdContact * * @Table(name="pd_contact") * @Entity */ class PdContact { /** * @var integer $id * * @Column(name="id", type="integer", nullable=false) * @Id * @GeneratedValue(strategy="IDENTITY") */ private $id; /** * @var string $name * * @Column(name="name", type="string", length=50, nullable=false) */ private $name; /** * @var string $email * * @Column(name="email", type="string", length=50, nullable=false) */ private $email; /** * @var string $subject * * @Column(name="subject", type="string", length=100, nullable=false) */ private $subject; /** * @var text $message * * @Column(name="message", type="text", nullable=false) */ private $message; /** * Get id * * @return integer $id */ public function getId() { return $this->id; } /** * Set name * * @param string $name */ public function setName($name) { $this->name = $name; } /** * Get name * * @return string $name */ public function getName() { return $this->name; } /** * Set email * * @param string $email */ public function setEmail($email) { $this->email = $email; } /** * Get email * * @return string $email */ public function getEmail() { return $this->email; } /** * Set subject * * @param string $subject */ public function setSubject($subject) { $this->subject = $subject; } /** * Get subject * * @return string $subject */ public function getSubject() { return $this->subject; } /** * Set message * * @param text $message */ public function setMessage($message) { $this->message = $message; } /** * Get message * * @return text $message */ public function getMessage() { return $this->message; } }
Now, lets create a model that will contain the database layer logic to insert submitted data from a contact form. Here it is:
require_once(APPPATH."models/Entities/PdContact.php"); use \PdContact; /** * manipulates data and contains data access logics for Enity 'User' * * @final Homemodel * @category models * @author Md. Ali Ahsan Rana * @link https://codesamplez.com */ class Homemodel extends CI_Model { /** * @var \Doctrine\ORM\EntityManager $em */ var $em; public function __construct() { parent::__construct(); $this->em = $this->doctrine->em; } /** * Add contact messages to database * @param array $contact_form * @return bool */ function add_message() { /** * @var PdContact $contact */ $contact = new PdContact(); $contact->setName($this->input->post("name"); $contact->setEmail($this->input->post("email"); $contact->setSubject($this->input->post("subject"); $contact->setMessage($this->input->post("message"); try { //save to database $this->em->persist($contact); $this->em->flush(); } catch(Exception $err){ die($err->getMessage()); } return true; } }
the above example will insert a new row to ‘pd_contact’ table with the posted data. Query execution will be in action when the “$this->em->flush();” is called. If there are more database operations, then those will be executed in this stage as a batch execution, which results faster performance then traditional query execution.
Using Doctrine Command Line Tool With Codeigniter:
If you are a CLI tool fan, you will might be more happier to know that, doctrine has support for command line! to add its support, we will have to create a file named ‘cli-config.php’ in current directory and add the following code in there:
$system_path = 'system'; $application_folder = 'application'; define('BASEPATH', str_replace("\\", "/", $system_path)); define('APPPATH', $application_folder.'/'); include __DIR__."/vendor/autoload.php"; include __DIR__."/application/libraries/doctrine.php"; $doctrine = new Doctrine(); $em = $doctrine->em; $helperSet = new \Symfony\Component\Console\Helper\HelperSet(array( 'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()), 'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em) )); return $helperSet;
Now we should be fine to use the tool. If all settings are OK, run ‘{path}/{to}/{cli}/doctrine’ and you should see some out like the below screenshot:
Other examples of commands can be as like below:
$./vendor/bin/doctrine orm:validate-schema $./vendor/bin/doctrine orm:generate:proxies ....
Note that, here I assumed you are using composer installed doctrine. Otherwise, use the proper cli tool path instead of ‘./vendor/bin/doctrine’.
Final Words:
Hope this tutorial on using doctrine with CodeIgniter will be very helpful to have a basic start for you. Ask if you have any questions or facing any issues. Keep in touch for more useful tutorials. Happy coding 🙂
Mehmet Aydın Bahadır says
Hi, thanks for this great tutorial. But i have a problem. When i close generate_classes() function, taking an error: Uncaught exception ‘Doctrine\ORM\Mapping\MappingException’ with message ‘Class Actions is not a valid entity or mapped super class.’
But after open this:
$this->em->getConfiguration()
->setMetadataDriverImpl(
new DatabaseDriver(
$this->em->getConnection()->getSchemaManager()
)
);
there’s no error but website is very slow. What can i do? I do everything as you say.
dionysis says
function generate_classes()
{
$this->em->getConfiguration()
->setMetadataDriverImpl(
new \Doctrine\ORM\Mapping\Driver\DatabaseDriver(
$this->em->getConnection()->getSchemaManager()
)
);
$cmf = new \Doctrine\ORM\Tools\DisconnectedClassMetadataFactory();
$cmf->setEntityManager($this->em);
$metadata = $cmf->getAllMetadata();
$generator = new \Doctrine\ORM\Tools\EntityGenerator();
$generator->setUpdateEntityIfExists(true);
$generator->setGenerateStubMethods(true);
$generator->setGenerateAnnotations(true);
$generator->generate($metadata, APPPATH.”models/Entities”);
}
Martin says
Auto generating entity classes code is not working..
Rana says
What issue you are having please?
nicx says
hi im totally a newbie with this doctrine, and i willing to learn. i cant figure out how to integrate doctrine and CI, need help. thanks in advance. when i will call the generate classes? DQL is like HQL but netbeans IDE generates entities easily. need help with this doctrine stuff. thanks
Rana says
you will need to call the generate class function only once, when you run the application on browser first time. Please let me know specifically in which other area you need help. Thanks.
mehmet soylu says
Fatal error: Uncaught exception ‘Doctrine\DBAL\DBALException’ with message ‘Unknown database type enum requested, Doctrine\DBAL\Platforms\MySqlPlatform may not support it.’ in D:\Projects\ci\application\third_party\doctrine-orm\Doctrine\DBAL\Platforms\AbstractPlatform.php:210
Rana says
Hi, when did you get this error please? did you created the databases and tables? My tutorial assumes so. by doctrine, its also possible to generate tables structure in db from running the application, but I didn’t cover that part in this tutorial.
alok kumar saxena says
Hi hehmet soylu,
You have to add just two lines of code in generate_class function.
$platform = $this->em->getConnection()->getDatabasePlatform();
$platform->registerDoctrineTypeMapping(‘enum’, ‘string’);
Thanks
Alok
sivaram says
Class “pdcontact” sub class of “” is not a valid entity or mapped super class.
i am facing this error what is the actual problem
Rana says
You have probably forgot to create the table in database I guess. If not, can you please share the details error screenshot please?
Rods says
Doesn’t work for me! I used git clone…but I’m receiving this error message:
Message: require_once(application/third_party/Doctrine/Common/ClassLoader.php) [function.require-once]: failed to open stream: No such file or directory
Filename: libraries/Doctrine.php
Rana says
Seems like, your file path is incorrect. can you please verify whether the file ‘ClassLoader.php’ is located at this path “application/third_party/Doctrine/Common/ClassLoader.php”?
Rods says
Thank’s very much. It was a wrong file path!
Jitesh says
Hi,
That’s nice but can you provide the download link for the source code.
It would help the newbee(beginners a lot).
Thanks
Raj
Md. Ali Ahsan Rana says
Hi Raj, I actually don’t have the code right now that I used on this tutorial. However, as a reference, you can use my ‘codeigniterplus’ project, https://github.com/ranacseruet/codeigniterplus, it has ready integration of doctrine in codeigniter and there I implemented some basic doctrine functionality. Hope it will help you. Let me know if you need anything else. Keep in touch. Thanks.
Latha says
hi., can anybody help me., how to authenticate username and password stored in db..??? i am newbie to code ignitor and doctrine. help me plz..
pusp raj joshi says
How to fetch data in view?
(
[users] => Array
(
[0] => Users Object
(
[id:Users:private] => 1
[ipAddress:Users:private] => 127.0.0.1
[username:Users:private] => administrator
[password:Users:private] => $2a$07$SeBknntpZror9uyftVopmu61qg0ms8Qv1yV6FG.kQOSM.9QhmTo36
[salt:Users:private] =>
[email:Users:private] => admin@admin.com
[activationCode:Users:private] =>
[forgottenPasswordCode:Users:private] =>
[forgottenPasswordTime:Users:private] =>
[rememberCode:Users:private] =>
[createdOn:Users:private] => 1268889823
[lastLogin:Users:private] => 1406821784
[active:Users:private] => 1
[firstName:Users:private] => Admin
[lastName:Users:private] => istrator
[company:Users:private] => ADMIN
[phone:Users:private] => 0
)
)
)
Md Ali Ahsan Rana says
You can simply use “$users[0]->getEmail()” (iterate for multiple entries) and similar syntax to show if on view. Hope this helps!
Musa Haidari says
Thank you to mention this part. Only I wanted to mention that I had the same problem but got confused how to solve this. What I did to solve it was to move the following piece code to the constructor of the Doctrine class, before the $this->generate_classes (); so it looks like:
class Doctrine {
/**
* @var EntityManager $em
*/
public $em = null;
/**
* constructor
*/
public function __construct()
{
//Other codes
//move this piece of code here
$this->em->getConfiguration()
->setMetadataDriverImpl(
new DatabaseDriver(
$this->em->getConnection()->getSchemaManager()
)
);
$this->generate_classes();
}
} // end of Doctrine class
tahseen says
i have followed your tutorial step by step working fine. when i comment out the function call in constructor and which create the entity classes .. and call the entity class in model it shows this error.
Class “Options” is not a valid entity or mapped super class.
any idea please…
omur says
Please help i cant solve this problem.
Fatal error: Uncaught exception ‘Doctrine\ORM\Mapping\MappingException’ with message ‘Class “Entity\User” is not a valid entity or mapped super class.’ in /home/u172335430/public_html/CI_Doctrine/application/libraries/Doctrine/ORM/Mapping/MappingException.php:336 Stack trace: #0 /home/u172335430/public_html/CI_Doctrine/application/libraries/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php(89): Doctrine\ORM\Mapping\MappingException::classIsNotAValidEntityOrMappedSuperClass(‘Entity\\User’) #1 /home/u172335430/public_html/CI_Doctrine/application/libraries/Doctrine/ORM/Mapping/ClassMetadataFactory.php(117): Doctrine\ORM\Mapping\Driver\AnnotationDriver->loadMetadataForClass(‘Entity\\User’, Object(Doctrine\ORM\Mapping\ClassMetadata)) #2 /home/u172335430/public_html/CI_Doctrine/application/libraries/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php(318): Doctrine\ORM\Mapping\ClassMetadataFactory->doLoadMetadata(Object(Doctrine\ORM\Mapping\ClassMetadata), NULL, false, Array) #3 /home/u172335430/public_html/CI_D in /home/u172335430/public_html/CI_Doctrine/application/libraries/Doctrine/ORM/Mapping/MappingException.php on line 336
janis says
i got this message when test this tutorial Class “PdContact” is not a valid entity or mapped super class.
so i need help to understantd