Doctrine, namespace and autoload entities

2019-05-17 20:24发布

问题:

I want to use Doctrine 2 in my project. I've some problems with it. I read the docs but probably I'm doing something wrong.

I want to autoload entities classes. And method from the docs is not working.

My bootstrap.php

<?php

require_once "vendor/autoload.php";
use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\Driver;

$paths = array("../Entities");
$isDevMode = false;

$classLoader = new \Doctrine\Common\ClassLoader('Entities','../Entities');
$classLoader->register();

// the connection configuration
$dbParams = array(
    'driver'   => 'pdo_mysql',
    'user'     => 'xxx',
    'password' => 'xxx',
    'dbname'   => 'xxx',
);

$driver = new Doctrine\ORM\Mapping\Driver\AnnotationDriver(new Doctrine\Common\Annotations\AnnotationReader(),array('../Entities'));
$config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);
$config->setMetadataDriverImpl($driver);
$em = EntityManager::create($dbParams, $config);

I've got my model's classes in Entities directory. I've generated them using doctrine client. They looks OK. There are ids, setters, getters and namespace at the beginning.

/Entities/ArticleCat.php

<?php

namespace Entities;

use Doctrine\ORM\Mapping as ORM;

/**
 * ArticleCat
 *
 * @ORM\Table(name="article_cat")
 * @ORM\Entity
 */
class ArticleCat
{

My script where I want to use doctrine:

<?php
  require_once 'bootstrap.php';

  $article = $em->find('ArticleCat', 21);
  echo $article->getName();

It's not working. It works only when I use it this way and I remove namespace from Entity model.

<?php
  require_once 'bootstrap.php';
  require_once 'Entities/ArticleCat.php'; //this line added (manual load)


  $article = $em->find('ArticleCat', 21);
  echo $article->getName();

What's the proper way of using doctrine and autoload entities? Why the namespace is a problem?

My errors:

Fatal error: Uncaught exception 'Doctrine\Common\Persistence\Mapping\MappingException' 
with message 'Class 'ArticleCat' does not exist' in 
/myproject/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/MappingException.php:96
Stack trace: #0 /myproject/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping/RuntimeReflectionService.php(40): 
Doctrine\Common\Persistence\Mapping\MappingException::nonExistingClass('ArticleCat') 
#1 /myproject/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping
   /AbstractClassMetadataFactory.php(267): Doctrine\Common\Persistence\Mapping
   \RuntimeReflectionService->getParentClasses('ArticleCat') 
#2 /myproject/vendor/doctrine/common/lib/Doctrine/Common/Persistence/Mapping
   /AbstractClassMetadataFactory.php(297): Doctrine\Common\Persistence\Mapping
   \AbstractClassMetadataFactory->getParentClasses('ArticleCat') 
#3 /myproject/vendor/doc in /myproject/vendor/doctrine/common/lib/Doctrine/Common/Persistence
   /Mapping/MappingException.php on line 96

回答1:

Try to use fully qualified class name with namespace. When you've got error about CG proxy classes try to generate your proxy classes by running

vendor/bin/doctrine orm:generate-proxies

good luck!



回答2:

If you are using composer, you want to be sure that you have the following 'autoload' in your composer.json:

{
        "require": {
           ...
        },
        "autoload": {
            "psr-0": {"": "Entity/"}
        }
}

This fixed the problem for me. I'm not using any namespace in my entity class though. My composer.json lives in my inc directory and the Entity directory referenced here is at inc/Entity.



回答3:

Hmm, I've always used the ClassLoader when it comes to using namespaces. I've had so much trouble with it that I 'm using a sort configuration class with all the path/to/src's I need.

E.g. if your path is path/to/src and your classname is Entities\ArticleCat then the directory structure for the location of the file ArticleCat.php is

src \
  Entities \
    ArticleCat.php

Now all you need to do is create a ClassLoader for Entities

$src = 'path/to/src'
$cl = new ClassLoader('Entities', $src);
$cl->register();

and class ArticleCat should now be available using the EntityManager

$articleCat = $em->getRepository('Entities\ArticleCat');
$article = $articleCat->find(21);
echo $article->getName();

or

$article = $em->find('Entities\ArticleCat', 21);
echo $article->getName();