Search code examples
phpzend-frameworknamespacesdoctrine-ormautoloader

Zend Framework 1.11 with Doctrine 2 and namespaces


I've been using Doctrine in my project without explicitly namespacing any of my classes. This led to some problems with trying to organise my code into separate sub directories (or at least it seemed to). As such I've tried to implement namespaces in my code but I'm struggling and having tried the numerous solutions on here to no avail, I need to ask.

I've got the standard project structure:

application/
--models/
--services/
--controllers/
..etc

In my Bootstrap I've got the following (without namespaces in my code which works fine):

/**
* Initialize Doctrine
* @return Doctrine_Manager
*/
public function _initDoctrine() {
    // include and register Doctrine's class loader
    require_once('doctrine/Doctrine/Common/ClassLoader.php');

    $autoloader = \Zend_Loader_Autoloader::getInstance();

    require_once('doctrine/Doctrine/Common/ClassLoader.php');
    $commonLoader = new \Doctrine\Common\ClassLoader('Doctrine\Common', 'doctrine');
    $autoloader->pushAutoloader(array($commonLoader, 'loadClass'), 'Doctrine\Common');

    $dbalLoader = new \Doctrine\Common\ClassLoader('Doctrine\DBAL', 'doctrine');
    $autoloader->pushAutoloader(array($dbalLoader, 'loadClass'), 'Doctrine\DBAL');

    $ormLoader = new \Doctrine\Common\ClassLoader('Doctrine\ORM', 'doctrine');
    $autoloader->pushAutoloader(array($ormLoader, 'loadClass'), 'Doctrine\ORM');

    $modelLoader = new \Doctrine\Common\ClassLoader(NULL, APPLICATION_PATH . "/models");
    $autoloader->pushAutoloader(array($modelLoader, 'loadClass'), '');

    // create the Doctrine configuration
    $config = new \Doctrine\ORM\Configuration();

    // setting the cache ( to ArrayCache. Take a look at
    // the Doctrine manual for different options ! )
    $cache = new \Doctrine\Common\Cache\ArrayCache;
    $config->setMetadataCacheImpl($cache);
    $config->setQueryCacheImpl($cache);

    // choosing the driver for our database schema
    // we'll use annotations
    $driver = $config->newDefaultAnnotationDriver(
        APPLICATION_PATH . '/models'
        );
    $config->setMetadataDriverImpl($driver);

    // set the proxy dir and set some options
    $config->setProxyDir(APPLICATION_PATH . '/models/Proxies');
    $config->setAutoGenerateProxyClasses(true);
    //$config->setAutoGenerateProxyClasses(false);
    $config->setProxyNamespace('App\Proxies');

    // now create the entity manager and use the connection
    // settings we defined in our application.ini
    $connectionSettings = $this->getOption('doctrine');
    $conn = array(
    'driver'    => $connectionSettings['conn']['driv'],
    'user'      => $connectionSettings['conn']['user'],
    'password'  => $connectionSettings['conn']['pass'],
    'dbname'    => $connectionSettings['conn']['dbname'],
    'host'      => $connectionSettings['conn']['host']
    );
    $entityManager = \Doctrine\ORM\EntityManager::create($conn, $config);

    // push the entity manager into our registry for later use
    $registry = Zend_Registry::getInstance();
    $registry->entitymanager = $entityManager;

    return $entityManager;
}

When I add

namespace models;

to each of my model classes and update the Bootstrap to be as follows I get an Exception "Class Application does not exist" (Application is one of my models):

$modelLoader = new \Doctrine\Common\ClassLoader('models', APPLICATION_PATH . "/models");
$autoloader->pushAutoloader(array($modelLoader, 'loadClass'), 'models');

Just for completeness, I reference that model in my controller as follows:

public function indexAction()
{
    $this->_helper->layout()->title = "Your applications";
    $this->_helper->layout()->description = "Create, edit and view all applications you have registered with us.";
    $this->view->applicationList = $this->entityManager->getRepository("Application")->findAll();
}

What am I missing? I'm sure it's obvious but really am pulling out my hair now.


Solution

  • After much futher searching, I stumbled across this video (login required).

    Basically, the way I solved (as per the webinar) was to namespace my entities and save them under the /library directory. Then whenever I need to use them from the actual app, I access via their namespace.