
Are you tired of CodeIgniter’s native database handling and craving the power of a robust ORM? Look no further! This comprehensive guide will show you exactly how to integrate Doctrine with CodeIgniter for a supercharged development experience.
Why Use Doctrine With CodeIgniter?
While CodeIgniter offers a decent Active Record pattern implementation for database operations, many developers (myself included) prefer working with a full-featured ORM. The combination of CodeIgniter’s lightweight framework and Doctrine’s powerful ORM capabilities creates an absolutely fantastic development environment.
I’ve previously covered CodeIgniter basics, but today I’m diving into something that will completely transform your CodeIgniter development experience. Doctrine integration solves one of CodeIgniter’s biggest limitations: the lack of a built-in ORM system.
What You’ll Learn in This Guide
- How to install and configure Doctrine with CodeIgniter
- Creating a custom library to handle the integration
- Generating entity classes from your database automatically
- Practical examples of using Doctrine within your CodeIgniter applications
- Setting up the command-line tools for advanced operations
Let’s get started with this game-changing integration!
Prerequisites
Before diving in, you should have:
- Basic knowledge of CodeIgniter framework
- Understanding of what Doctrine is and its basic concepts
- PHP 5.3+ installed on your server (Doctrine requires namespaces)
Installation and Setup
Step 1: Download and Install Doctrine
First, you need to get your hands on the latest Doctrine ORM package. You have two options:
Option 1: Direct Download
- Download the latest Doctrine ORM from the official website
- Extract the contents
- Copy the extracted ‘doctrine’ directory to your CodeIgniter application’s ‘third_party’ directory
Option 2: Using Composer (Recommended) If you’re already using Composer with CodeIgniter (which is a fantastic practice), simply add Doctrine as a dependency in your composer.json file:
"require": {
"doctrine/orm": "^2.14"
}Code language: JavaScript (javascript)Then run composer update to install Doctrine and its dependencies.
Step 2: Create the Doctrine Library
Now, let’s create a custom library to handle the Doctrine initialization. Create a new file named ‘Doctrine.php’ in your ‘application/libraries’ directory:
<?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 Doctrine Integration
*
* A custom library that initializes Doctrine ORM within CodeIgniter
*
* @author Md. Ali Ahsan Rana
* @link https://codesamplez.com/
*/
class Doctrine
{
/**
* @var EntityManager $em
*/
public $em = null;
/**
* Constructor - Sets up Doctrine integration
*/
public function __construct()
{
// Load database configuration from CodeIgniter
require APPPATH.'config/database.php';
// Set up class loading
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);
// Set up driver
$driverImpl = $config->newDefaultAnnotationDriver(array(APPPATH.'models/Entities'));
$config->setMetadataDriverImpl($driverImpl);
$config->setQueryCacheImpl($cache);
// Proxy configuration
$config->setProxyDir(APPPATH.'models/proxies');
$config->setProxyNamespace('Proxies');
// Enable auto-generation of proxy classes for development
$config->setAutoGenerateProxyClasses(TRUE);
// Database connection from CI config
$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);
// Uncomment the line below once to generate entities, then comment it out again
// $this->generate_entities();
}
/**
* Generate entity classes automatically from database tables
*
* @return void
*/
public function generate_entities()
{
// Register MySQL types with Doctrine
$platform = $this->em->getConnection()->getDatabasePlatform();
$platform->registerDoctrineTypeMapping('enum', 'string');
// Set up metadata driver from database schema
$this->em->getConfiguration()
->setMetadataDriverImpl(
new DatabaseDriver(
$this->em->getConnection()->getSchemaManager()
)
);
// Create metadata factory
$cmf = new DisconnectedClassMetadataFactory();
$cmf->setEntityManager($this->em);
$metadata = $cmf->getAllMetadata();
// Configure entity generator
$generator = new EntityGenerator();
$generator->setUpdateEntityIfExists(true);
$generator->setGenerateStubMethods(true);
$generator->setGenerateAnnotations(true);
// Generate entities
$generator->generate($metadata, APPPATH."models/Entities");
}
}Code language: HTML, XML (xml)IMPORTANT ⚠️: This implementation requires PHP 5.3+ because it uses namespaces. Make sure your server supports this version or higher.
Step 3: Create Required Directories
You’ll need to create two directories inside your ‘application/models’ folder:
application/models/Entities– This will store your entity classesapplication/models/proxies– For Doctrine’s proxy classes
Step 4: Load the Library
To use Doctrine in your application, you need to load it. The best approach is to autoload it by adding ‘doctrine’ to your autoload.php config file:
$autoload['libraries'] = array('database', 'doctrine');Code language: PHP (php)Generating Entity Classes From Your Database
One of the most powerful features of Doctrine is the ability to generate entity classes directly from your existing database structure. The generate_entities() method in our Doctrine library handles this process.
Pro Tip 💡: Only call the generate_entities() method once when you first set up your application or when your database structure changes. Comment it out after running it once to avoid performance issues.
How Entity Generation Works
The entity generation process:
- Examines your database schema using Doctrine’s DatabaseDriver
- Creates metadata for each table structure
- Generates PHP entity classes with proper annotations
- Places these classes in your
application/models/Entitiesdirectory
When you run your application with the generate_entities() method uncommented, Doctrine will create entity classes for all your database tables.
A Real-World Example: Contact Form
Let’s apply what we’ve learned to a practical example – handling a contact form submission with Doctrine.
Step 1: Create the Database Table
First, create a table in your MySQL database:
CREATE TABLE `pd_contact` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`email` varchar(50) NOT NULL,
`subject` varchar(100) NOT NULL,
`message` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;Code language: JavaScript (javascript)Step 2: Generate the Entity Class
After running your application with the generate_entities() method active, Doctrine will create a PdContact.php entity class in your application/models/Entities directory. It should look something like this:
<?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;
// Getters and setters are automatically generated
// ...
}Code language: HTML, XML (xml)Step 3: Create a Model for Business Logic
Now, let’s create a model that will handle the business logic for our contact form:
<?php
require_once(APPPATH."models/Entities/PdContact.php");
use \PdContact;
/**
* Home model for contact form operations
*/
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
*
* @return bool
*/
function add_message()
{
// Create a new entity instance
$contact = new PdContact();
// Set properties from form data
$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();
return true;
} catch(Exception $err) {
log_message('error', $err->getMessage());
return false;
}
}
/**
* Get all contact messages
*
* @return array
*/
function get_all_messages()
{
return $this->em->getRepository('PdContact')->findAll();
}
}Code language: HTML, XML (xml)Step 4: Use in Your Controller
Finally, you can use this model in your controller:
<?php
class Contact extends CI_Controller
{
public function __construct()
{
parent::__construct();
$this->load->model('homemodel');
}
public function index()
{
$this->load->view('contact_form');
}
public function submit()
{
if ($this->homemodel->add_message()) {
$this->session->set_flashdata('success', 'Message sent successfully!');
} else {
$this->session->set_flashdata('error', 'Failed to send message.');
}
redirect('contact');
}
}Code language: HTML, XML (xml)Tip 💡: Level up your web development skill with our codeigniter learning roadmap
Using Doctrine’s Command Line Tools
Doctrine provides powerful command line tools for various operations like schema validation, entity generation, and more. Let’s set them up for use with CodeIgniter.
Creating the CLI Configuration
Create a file named cli-config.php in your project’s root directory:
<?php
$system_path = 'system';
$application_folder = 'application';
define('BASEPATH', str_replace("\\", "/", $system_path));
define('APPPATH', $application_folder.'/');
// Include composer autoloader if using composer
include __DIR__."/vendor/autoload.php";
// Include our Doctrine library
include __DIR__."/application/libraries/doctrine.php";
// Initialize Doctrine
$doctrine = new Doctrine();
$em = $doctrine->em;
// Set up helper set for command line tools
$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: HTML, XML (xml)Using the Command Line Tools
Now you can use Doctrine’s command line tools. Here are some examples:
# Validate your schema
./vendor/bin/doctrine orm:validate-schema
# Generate proxy classes
./vendor/bin/doctrine orm:generate-proxies
# Create schema from entities
./vendor/bin/doctrine orm:schema-tool:createCode language: PHP (php)Advanced Usage Tips
1. Working with Repository Classes
For complex queries, you can create custom repository classes:
<?php
// In Entity class
/**
* @Entity(repositoryClass="PdContactRepository")
*/
class PdContact
{
// ...
}
// In Repository class
class PdContactRepository extends \Doctrine\ORM\EntityRepository
{
public function findRecent($limit = 5)
{
return $this->createQueryBuilder('c')
->orderBy('c.id', 'DESC')
->setMaxResults($limit)
->getQuery()
->getResult();
}
}Code language: HTML, XML (xml)2. Handling Relationships
Doctrine makes it easy to work with relationships between entities:
<?php
/**
* @Entity
*/
class User
{
/**
* @OneToMany(targetEntity="PdContact", mappedBy="user")
*/
private $contacts;
public function __construct()
{
$this->contacts = new \Doctrine\Common\Collections\ArrayCollection();
}
// ...
}
/**
* @Entity
*/
class PdContact
{
/**
* @ManyToOne(targetEntity="User", inversedBy="contacts")
*/
private $user;
// ...
}Code language: HTML, XML (xml)3. Using DQL for Complex Queries
Doctrine Query Language (DQL) is extremely powerful for complex data retrieval:
$query = $this->em->createQuery('
SELECT c FROM PdContact c
WHERE c.email LIKE :email
ORDER BY c.id DESC
');
$query->setParameter('email', '%gmail.com');
$results = $query->getResult();Code language: PHP (php)Troubleshooting Common Issues
Issue 1: “Class is not a valid entity or mapped super class”
This often happens when:
- You haven’t generated entity classes correctly
- The namespace is wrong
- You’re trying to use an entity without requiring/importing it
Solution: Make sure your entity class has the @Entity annotation and is properly imported.
Issue 2: “Unknown database type enum requested”
Doctrine doesn’t natively support MySQL’s ENUM type.
Solution: Add type mapping in the generate_entities() method:
$platform = $this->em->getConnection()->getDatabasePlatform();
$platform->registerDoctrineTypeMapping('enum', 'string');Code language: PHP (php)Issue 3: “Failed to open stream: No such file or directory”
This usually indicates incorrect file paths.
Solution: Double-check your directory structure and make sure all paths are correct.
Conclusion
Integrating Doctrine with CodeIgniter gives you the best of both worlds – a lightweight, fast framework paired with a powerful ORM system. This combination provides incredible flexibility for your PHP applications, particularly when dealing with complex database operations.
By following this guide, you now have a robust integration that allows you to:
- Use object-oriented database access
- Generate entity classes automatically
- Leverage Doctrine’s powerful query capabilities
- Maintain clean, maintainable code
Remember to use the generate_entities() method only when necessary, and take advantage of Doctrine’s command line tools for advanced operations.
Have you implemented Doctrine with CodeIgniter in your projects? What challenges did you face? Share your experience in the comments below!
Happy coding with Doctrine and CodeIgniter!
Discover more from CodeSamplez.com
Subscribe to get the latest posts sent to your email.

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.
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”);
}
Auto generating entity classes code is not working..
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] => [email protected]
[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