I have already discussed a 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 queries. However, database support in Codeigniter is still not good enough for many. Especially many developers prefer to work with ORM for the database layer, and CodeIgniter doesn’t provide such built-in support. However, doctrine is a mighty 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 the 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. So, In this tutorial, I will show how we can integrate this doctrine with CodeIgniter. The following will show some basic usage with examples of PHO code. I am assuming you have some basic knowledge of CodeIgniter. A basic understanding of what doctrine is and how it works is 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 by adding a dependency on composer.json as below:
"require": {
"doctrine/orm": "dev-master"
}
Code language: JavaScript (javascript)
Now, in the ‘application/libraries’ directory, let’s 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);
}
}
Code language: PHP (php)
NOTE: The above code requires the PHP 5.3.x version to be installed on your server.
The above class is almost the same as the one described in the 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 the CodeIgniter’s database configuration and doctrine class to load the necessary classes. Then, it loads some necessary items. To know more in detail about the configuration options and how they work, please refer to the 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");
}
Code language: PHP (php)
Remember, activate calling using this method only once. And then after the entity classes are generated, keep it commented, otherwise you may get errors. If sometimes, database structure changes/tables are 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. Let’s create a table on our MySQL database named ‘pd_contact’ as like follows:
This will generate an entity class as 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;
}
}
Code language: HTML, XML (xml)
Now, let’s 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;
}
}
Code language: PHP (php)
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 in faster performance than traditional query execution.
Using Doctrine Command Line Tool With Codeigniter:
If you are a CLI tool fan, you will be happier to know that the doctrine supports the command line! To add its support, we will have to create a file named ‘cli-config.php’ in the current directory and add the following code 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;
Code language: PHP (php)
Now, we should be fine with using 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 follows:
$./vendor/bin/doctrine orm:validate-schema
$./vendor/bin/doctrine orm:generate:proxies
....
Code language: JavaScript (javascript)
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 are 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?
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
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.
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
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.
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
Class “pdcontact” sub class of “” is not a valid entity or mapped super class.
i am facing this error what is the actual problem
You have probably forgot to create the table in database I guess. If not, can you please share the details error screenshot please?
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
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”?
Thank’s very much. It was a wrong file path!
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
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.
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..
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
)
)
)
You can simply use “$users[0]->getEmail()” (iterate for multiple entries) and similar syntax to show if on view. Hope this helps!
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
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…
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
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