web-dev-qa-db-fra.com

Obtenir uniquement l'ID des relations d'entité sans récupérer l'objet entier dans Doctrine

Supposons que j'ai une entité qui se référence pour mapper les relations parent-enfant

class Food
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\ManyToOne(targetEntity="Food", inversedBy="foodChildren")
     * @ORM\JoinColumn(name="food_group_id", nullable=true)
     */
    protected $foodGroup;

    /**
     * @ORM\OneToMany(targetEntity="Food", mappedBy="foodGroup", fetch="LAZY", cascade={"remove"})
     */
    protected $foodChildren;

J'ai un cas d'utilisation où je veux obtenir food_group_id D'une entité sans obtenir l'objet parent complet de la base de données. L'utilisation de fetch="LAZY" N'empêche pas Doctrine d'interroger à nouveau. Existe-t-il un moyen de renvoyer uniquement l'ID lors de l'obtention de $food->getFoodGroup()?

35
rabudde

Ne compliquez pas votre vie, vous pouvez simplement le faire

$food->getFoodGroup()->getId()

Cela NE SERA PAS effectuer une requête supplémentaire ou déclencher un chargement paresseux!

Pourquoi? Parce que votre $food->foodGroup est un objet proxy qui connaît son ID. Il ne fera un chargement différé que si vous appelez une méthode getter d'un champ qui n'a pas été chargé.

90
Igor Pantović

Vous pouvez utiliser

$em->getUnitOfWork()->getEntityIdentifier(...);

pour obtenir des identifiants sans faire de jointures.

Dans votre exemple, ce serait quelque chose comme ceci:

$em = $this->getDoctrine()->getManager();
$food = $em->getRepository('HungryHungryBundle:Food')->findOneById($id);
print_r($em->getUnitOfWork()->getEntityIdentifier($food->getFoodGroup())); 
die();

De cette façon, vous obtiendrez le food_group_id sans faire de jointure supplémentaire.

4
Noquepoaqui

Vous devez être en mesure de définir le champ ID, de l'associer à l'ORM, puis de créer le getter pour ce champ, et cela devrait fonctionner.

/**
 * @ORM\ManyToOne(targetEntity="Food", inversedBy="foodChildren")
 * @ORM\JoinColumn(name="foodGroupId", referencedColumnName="id")
 */
protected $foodGroup;

/**
 * @ORM\Column(type="integer")
 */
protected $foodGroupId;

public function getFoodGroupId() {
    return $this->foodGroupId;
}

Remarque, j'ai changé le nom du champ dans mon exemple en Pascal Case, pour des raisons de cohérence. De plus, je suis nouveau sur Symfony, mais votre mappage d'association ManyToOne semble étrange. Je ne sais pas pourquoi vous avez annulable sur l'entité (je ne l'ai pas vu auparavant). Vous n'avez pas de referencedColumnName = "id", mais c'est peut-être simplement parce qu'il est par défaut "id" (j'aime être explicite). Voir Doctrine docs .

J'ai eu un très problème similaire , qui a été causé simplement parce que je n'avais pas associé ce champ à l'ORM. Vous devez donc savoir qu'il IS possible d'appeler:

$food = $em->getRepository("AcmeFoodBundle:Food")->find($id);
$food->getFoodGroupId();
2
Chadwick Meyer

Je ne sais pas s'il s'agit d'un problème de performances et vous essayez de limiter les requêtes, mais pourquoi ne pas simplement faire quelque chose comme ça dans votre getter (je suppose que c'est votre entité Food en utilisant Doctrine Annotations ORM):

class Food
{
    ...
    public function getFoodGroup() {
        $foodGroup = $this->getFoodGroup();

        return $foodGroup->getId();
    }

ou encore mieux le nommer de manière appropriée getFoodGroupId()

0
Ken Hannel