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.
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.
Let’s get started with this game-changing integration!
Before diving in, you should have:
First, you need to get your hands on the latest Doctrine ORM package. You have two options:
Option 1: Direct Download
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.
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.
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 classesTo 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) 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.
The entity generation process:
application/models/Entities directoryWhen you run your application with the generate_entities() method uncommented, Doctrine will create entity classes for all your database tables.
Let’s apply what we’ve learned to a practical example – handling a contact form submission with Doctrine.
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) 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) 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) 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
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.
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) 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) 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) 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) 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) This often happens when:
Solution: Make sure your entity class has the @Entity annotation and is properly imported.
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) This usually indicates incorrect file paths.
Solution: Double-check your directory structure and make sure all paths are correct.
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:
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!
Learn python file handling from scratch! This comprehensive guide walks you through reading, writing, and managing files in Python with real-world examples, troubleshooting tips, and…
You've conquered the service worker lifecycle, mastered caching strategies, and explored advanced features. Now it's time to lock down your implementation with battle-tested service worker…
Unlock the full potential of service workers with advanced features like push notifications, background sync, and performance optimization techniques that transform your web app into…
This website uses cookies.
View Comments
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] => 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!