How to install Doctrine in CodeIgniter 3
For CI3 + HMVC + Doctrine 2.4
<?php
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Cache\ArrayCache;
use Doctrine\Common\ClassLoader;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\Event\Listeners\MysqlSessionInit;
use Doctrine\DBAL\Logging\EchoSQLLogger;
use Doctrine\ORM\Configuration;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\Driver\AnnotationDriver;
use Doctrine\ORM\Tools\SchemaTool;
use Gedmo\Sluggable\SluggableListener;
use Gedmo\Timestampable\TimestampableListener;
use Gedmo\Tree\TreeListener;
class Doctrine
{
public $em = null;
public $tool = null;
public function __construct()
{
// Is the config file in the environment folder?
if (!defined('ENVIRONMENT') OR !file_exists($file_path = APPPATH . 'config/' . ENVIRONMENT . '/database.php')) {
$file_path = APPPATH . 'config/database.php';
}
// load database configuration from CodeIgniter
require $file_path;
// Set up class loading. You could use different autoloaders, provided by your favorite framework,
// if you want to.
require_once APPPATH . 'vendor/doctrine/common/lib/Doctrine/Common/ClassLoader.php';
$doctrineClassLoader = new ClassLoader('Doctrine', APPPATH . 'libraries');
$doctrineClassLoader->register();
$entitiesClassLoader = new ClassLoader('models', rtrim(APPPATH, "/"));
$entitiesClassLoader->register();
$proxiesClassLoader = new ClassLoader('Proxies', APPPATH . 'proxies');
$proxiesClassLoader->register();
foreach (glob(APPPATH . 'modules/*', GLOB_ONLYDIR) as $m) {
$module = str_replace(APPPATH . 'modules/', '', $m);
$loader = new ClassLoader($module, APPPATH . 'modules');
$loader->register();
}
$evm = new EventManager;
// timestampable
$evm->addEventSubscriber(new TimestampableListener);
// sluggable
$evm->addEventSubscriber(new SluggableListener);
// tree
$evm->addEventSubscriber(new TreeListener);
// 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);
$config->setQueryCacheImpl($cache);
// Proxy configuration
$config->setProxyDir(APPPATH . '/proxies'); //must be set to 777
$config->setProxyNamespace('Proxies');
// Set up logger
$logger = new EchoSQLLogger;
$config->setSQLLogger($logger);
if (ENVIRONMENT == "development") {
$config->setAutoGenerateProxyClasses(true);
} else {
$config->setAutoGenerateProxyClasses(false);
}
// Database connection information
$connectionOptions = array(
'driver' => 'pdo_mysql',
'user' => $db[$active_group]['username'],
'password' => $db[$active_group]['password'],
'host' => $db[$active_group]['hostname'],
'dbname' => $db[$active_group]['database']
);
// Create EntityManager
$this->em = EntityManager::create($connectionOptions, $config);
// Force UTF-8
$this->em->getEventManager()->addEventSubscriber(new MysqlSessionInit('utf8', 'utf8_unicode_ci'));
// Schema Tool
$this->tool = new SchemaTool($this->em);
}
}
Install Doctrine
(The following instructions are modified from: Doctrine 2 ORM’s documentation - Installation and Configuration)
Doctrine can be installed with Composer:
From your command line (e.g. Windows: Start > cmd), change to the folder where the files should be installed (e.g. htdocs/my_project).
Use Composer to install the files:
a. run
C:\>composer install doctrine/orm
or:
b. Define the following requirement in your composer.json file:
{ "require": { "doctrine/orm": "*" } }
and then call
composer install
from your command line.
Composer will install a folder vendor
with numerous sub-folders and several hundred php files. Move this vendor
folder into your CodeIgniter application tree. For simplicity, you could put it here:
/application
/config
/controllers
/libraries
Doctrine.php <-- the doctrine bootstrap/wrapper file
/third_party
/vendor <-- the folder installed by Composer. don't touch the files or folders below it -- install all together as one happy family.
/bin
/composer
/doctrine
/symfony
autoload.php <-- Doctrine.php opens this to load its files
then in your library file Doctrine.php
(see below) you would just:
require_once FCPATH . 'vendor/autoload.php'; // FCPATH is a CI constant specifies the path to the front controller.
You could also install all the folders and files contained inside vendor
elsewhere, say in third_party
and adjust your Doctrine.php accordingly.
Integrating with CodeIgniter
(The following instructions are modified from: Doctrine 2 ORM’s documentation - Integrating with CodeIgniter)
Create your Doctrine library: In your folder
system/application/libraries
, create a file namedDoctrine.php
and copy/paste the following code into the file. This is going to be your wrapper/bootstrap for the Doctrine2 entity manager.Your Doctrine.php library file should look like this (you may customize it to your needs):
<?php /** * Doctrine 2.4 bootstrap * */ use Doctrine\Common\ClassLoader, Doctrine\ORM\Configuration, Doctrine\ORM\EntityManager, Doctrine\Common\Cache\ArrayCache, Doctrine\DBAL\Logging\EchoSQLLogger; class Doctrine { public $em = null; public function __construct() { // load database configuration from CodeIgniter require_once APPPATH.'config/database.php'; // load Doctrine require_once FCPATH . 'vendor/autoload.php'; // or, if you installed another way, you could: // require_once APPPATH.'third_party/Doctrine/Common/ClassLoader.php'; // load the Doctrine classes $doctrineClassLoader = new ClassLoader('Doctrine', APPPATH.'libraries'); // or, if installed in third_party: // $doctrineClassLoader = new ClassLoader('Doctrine', APPPATH.'third_party'); $doctrineClassLoader->register(); // load the entities $entityClassLoader = new ClassLoader('Entities', APPPATH.'models'); $entityClassLoader->register(); // load the proxy entities $proxiesClassLoader = new ClassLoader('Proxies', APPPATH.'models/proxies'); $proxiesClassLoader->register(); // load Symfony2 classes // this is necessary for YAML mapping files and for Command Line Interface (cli-doctrine.php) $symfonyClassLoader = new ClassLoader('Symfony', APPPATH.'third_party/Doctrine'); $symfonyClassLoader->register(); // Set up the configuration $config = new Configuration; // Set up caches if(ENVIRONMENT == 'development'): // set environment in index.php // set up simple array caching for development mode $cache = new \Doctrine\Common\Cache\ArrayCache; else: // set up caching with APC for production mode $cache = new \Doctrine\Common\Cache\ApcCache; endif; $config->setMetadataCacheImpl($cache); $config->setQueryCacheImpl($cache); // set up annotation driver $driver = new \Doctrine\ORM\Mapping\Driver\PHPDriver(APPPATH.'models/Mappings'); $config->setMetadataDriverImpl($driver); // Proxy configuration $config->setProxyDir(APPPATH.'/models/Proxies'); $config->setProxyNamespace('Proxies'); // Set up logger (recommended to remove for production) $logger = new EchoSQLLogger; $config->setSQLLogger($logger); $config->setAutoGenerateProxyClasses( TRUE ); // only for development // 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, and store it for use in our CodeIgniter controllers $this->em = EntityManager::create($connectionOptions, $config); } }
Load the doctrine library: either autoload your Doctrine library by adding it to the array in your
application/config/autoload.php
file:'$autoload[‘libraries’] = array(‘doctrine’);`
or load it manually in your controller like any other library by using:
$this->load->library('doctrine');
If you installed Doctrine.php in applications/third_party
, you would use:
$autoload[‘libraries’] = array('third_party/doctrine');
or
$this->load->library('third_party/doctrine');
An example controller is provided below in What's next.
Setting up the Command Line Tool
Doctrine ships with a number of command line tools that are very helpful during development.
Check if these lines exists in the Doctrine.php file, to load Symfony classes for using the Command line tools (and for YAML mapping files):
$symfonyClassLoader = new ClassLoader('Symfony', APPPATH.'third_party/Doctrine');
$symfonyClassLoader->register();
You need to register your applications EntityManager to the console tool to make use of the tasks by creating a cli-doctrine.php file in the application directory with the following content:
<?php
/**
* Doctrine CLI bootstrap for CodeIgniter
*
*/
define('APPPATH', dirname(__FILE__) . '/');
define('BASEPATH', APPPATH . '/../system/');
define('ENVIRONMENT', 'development');
require APPPATH.'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)
));
\Doctrine\ORM\Tools\Console\ConsoleRunner::run($helperSet);
?>
Now run this script through the PHP command-line and should see a list of commands available to you.
php cli-doctrine.php
Generate mapping classes from database:
php cli-doctrine.php orm:convert-mapping --from-database annotation models/Entities
if you get this error: Fatal error: Call to undefined function Doctrine\Common\Cache\apc_fetch() install the APC extension for PHP:
sudo apt-get install php-apc
sudo /etc/init.d/apache2 restart
For production mode:
Doctrine recommends changing the following settings in Doctrine.php:
- use a real caching system like APC
- disable EchoSqlLogger
- turn off autoGenerateProxyClasses
What's next
To use Doctrine in CI, call it from a controller, for example:
application/controllers/my_controller.php:
function doctrine_orm()
{
$this->load->library('Doctrine');
$em = $this->doctrine->em;
// do Doctrine stuff
$productRepository = $em->getRepository('Product');
$products = $productRepository->findAll();
foreach ($products as $product):
echo sprintf("-%s\n", $product->getName());
endforeach;
}
Before doing any Doctrine stuff, however, you must first map your database tables to Doctrine "entities". Learn how here: https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/tutorials/getting-started.html