Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to install Doctrine in CodeIgniter 3

The official guide is not complete, and others are for CI2.

So i give you a tutorial i myself checked is working.

I know SO encourage users to answer their own questions.

like image 202
Luca Mori Polpettini Avatar asked Oct 19 '15 08:10

Luca Mori Polpettini


2 Answers

Install Doctrine

(The following instructions are modified from: Doctrine 2 ORM’s documentation - Installation and Configuration)

Doctrine can be installed with Composer:

  1. From your command line (e.g. Windows: Start > cmd), change to the folder where the files should be installed (e.g. htdocs/my_project).

  2. 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)

  1. Create your Doctrine library: In your folder system/application/libraries, create a file named Doctrine.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);
      }
    }
    
  2. 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

like image 140
Luca Mori Polpettini Avatar answered Nov 15 '22 21:11

Luca Mori Polpettini


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);

    }
}
like image 1
Aymen Avatar answered Nov 15 '22 21:11

Aymen