Getting Started Tutorial On Using Doctrine With CodeIgniter


 Getting Started Tutorial On Using Doctrine With CodeIgniter  
 


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 a official help tutorial to do so, Integrate Doctrine With Codeigniter. 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 doctrine with codeigniter. This will follow will show some basic usage with php 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 a 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. Then, 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:

<?php
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	http://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 an contact form example to understand how to use doctrine orm within codeigniter. Lets create an table on our mysql database named ‘pd_contact’ as like follows:
mysql contact table schema example

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 http://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.

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. Happy coding :)

Comments

  1. 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.

  2. 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”);
    }

  3. 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

    • 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.

  4. 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

    • 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.

  5. 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

  6. 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

  7. Jitesh says

    Hi,

    Thats nice but can you provide the download link for the source code.
    It would help the newbee(begineers a lot).

    Thanks
    Raj

  8. 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..

Trackbacks

Leave a Reply