Bonjour,

Voila je rencontre un petit problème avec mon code. Je suis en train d'intégrer Doctrine ORM dans mon micro-framework maison.
La génération du schéma fonctionne correctement, mais lorsque j'essaye de récupérer une repository ce n'est pas possible.

Ce que je fais

Voici la configuration que j'utilise:

 EntityManager::class => function (ContainerInterface $c) {
            // the connection configuration
            $dbParams = array(
                'driver' => 'pdo_mysql',
                'user' => $c->get("database.username"),
                'password' => $c->get("database.password"),
                'dbname' => $c->get("database.name"),
                'host' => $c->get("database.host")
            );
            $paths = [dirname(__DIR__) . DIRECTORY_SEPARATOR . "src" . DIRECTORY_SEPARATOR . "Database" . DIRECTORY_SEPARATOR . "Entity"];
            //$paths = [dirname(__DIR__) . DIRECTORY_SEPARATOR . "src" . DIRECTORY_SEPARATOR];
            $isDevMode = $c->get("mode") === Mode::DEVELOPPEMENT;
            $config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);
            return EntityManager::create($dbParams, $config);;
        },

J'utilise le conteneur injecteur de dépendance PHP-DI

Voici une des Entity générée par Doctrine:

<?php

use Doctrine\ORM\Mapping as ORM;

/**
 * Products
 *
 * @ORM\Table(name="products")
 * @ORM\Entity
 */
class Products
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255, nullable=false)
     */
    private $name;

    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\ManyToMany(targetEntity="User", mappedBy="product")
     */
    private $user;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->user = new \Doctrine\Common\Collections\ArrayCollection();
    }

}

Et voici la manière dont je veux récupérer l'entity repository:

$manager = $this->container->get(EntityManager::class);
$manager->getRepository("Products");

Ce que j'obtiens

Au lancement de ce code une Exception est levée:

Doctrine \ ORM \ Mapping \ MappingException
Class "Products" is not a valid entity or mapped super class.

Peut-être que j'ai raté quelque chose, j'ai suivis ce qu'il y avait dans la documentation: Documentation

Merci à l'avance !!

11 réponses


gtnsimon
Réponse acceptée

@Lartak ce n'est pas un problème de pluriel ou singulier ici... si c'est le nom qu'il veut lui donner why not.

Chez moi aussi j'ai testé sur un projet où j'importe Doctrine ORM via Composer et j'ai la même exception si je déclare l'entité comme sur la documentation :

<?php

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="users")
 */

mais pas quand j'importe chaque classe des Annotations comme ceci :

<?php

use Doctrine\ORM\Mapping\{Entity, Table};

/**
 * @Entity
 * @Table(name="users")
 */

J'ai trouvé une issue sur Github : Annotation Parser does not replace namespace aliases #188 et en effet lorsque j'init. la configuration de Dotrine avec $useSimpleAnnotationReader à false, ça fonctionne !

Du coup tu peux soit modifier ta config (que tu as montré plus haut) ou faire les use 1 par 1... pour ma part je fais ça car j'utilise Symfony Validator avec les Annotations et ça plante par la suite donc j'ai pas cherché à résoudre le problème... (si je trouve je te dis)

<?php
// le prototype de la méthode
public static function createAnnotationMetadataConfiguration(array $paths, $isDevMode = false, $proxyDir = null, Cache $cache = null, $useSimpleAnnotationReader = true);
gtnsimon
Réponse acceptée

Trouvé, pour corriger le problème de chargement des annotations du Validator la solution est ici : https://github.com/dflydev/dflydev-doctrine-orm-service-provider#why-arent-my-annotations-classes-being-found

<?php
$loader = require __DIR__ . '/../vendor/autoload.php';

\Doctrine\Common\Annotations\AnnotationRegistry::registerLoader(array($loader, 'loadClass'));

Bonjour,

Est-ce que tu utilises Composer pour gérer ton projet / charger les dépendances ?

  1. Si oui, tu n'as pas déclaré de namespace dans ta classe Products, ce qui pourrait expliquer l'exception Doctrine car Composer ne sait pas comment trouver le fichier Products.php...
  2. Sinon, tu dois faire un require de ta classe avant de l'utiliser...
<?php
require __DIR__ . '/chemin/vers/Products.php';

// pour charger la classe j'aime bien utiliser la syntaxe PHP
// qui revient à écrire "Products" mais si tu as un namespace, c'est plus "propre", tu t'embêtes pas
$manager->getRepository(Products::class);

C'est une piste avant d'aller plus loin... la classe générée par Doctrine me semble bonne sinon.

j'utilise l'autoloader de composer en PSR-4 la Class est bien chargée :/

Ok, et si tu commentes la propriété "private $user;" ?
La relation @ORM\ManyToMany(targetEntity="User", mappedBy="product") est bonne sur la classe User ?

Bonjour.

j'utilise l'autoloader de composer en PSR-4 la Class est bien chargée :/

Pourtant tu ne définies pas le namespace dans ta classe Products.

si comme dans la documentation par namespace global:
{"":"src/Database/Entity"}

Je vais essayer de commenter user, c'est le code généré par doctrine surtout que je viens de remarquer dans le mapped by "product" il manque un "s". Je test et je vous tiens au courant

Je crois surtout que tu ne comprends pas ce qu'est une entité, une entité se réfère à un enregistrement d'une table, et non à l'ensemble d'une table.
C'est d'ailleurs pour ça qu'en général une classe correspondant à une entité se nomme au singulier, et non au pluriel comme c'est ton cas, par conséquence, ta classe devrait plutôt se nommer Product et non Products.

L'entity a été générée par Doctrine. le nom de ma table était au pluriel. Avant de dire ce genre de chose il faut aussi lire ce qui est plus haut.

Super ! Merci à toi ! N'hésite pas à me dire si tu trouve la solution ! :)