PRÉSENTATION DU COURS

Comprendre et utiliser des relations

Comprendre comment se forment les relations et comment les utiliser dans son code

Comprendre les relations doctrine dans les entités

Si vous ouvrez vos entités Monkey et Enclos, vous allez voir que symfony a ajouté un petit peu de code dans chacune des entités :

// fichier Monkey.php

//...

    /**
    * @ORM\ManyToOne(targetEntity="App\Entity\Enclos", inversedBy="monkeys")
    */
    private $enclos;

//...

    public function getJelly(): ?Enclos
    {
        return $this->jelly;
    }

    public function setJelly(?Enclos $jelly): self
    {
        $this->jelly = $jelly;

        return $this;
    }

Ici, Doctrine nous ajouté une nouvelle propriété permettant de tenir la relation du singe vers l'enclos, ainsi qu'un moyen de mettre à jour et récupérer cette relation.

Si vous avez répondu oui à cette question : Do you want to add a new property to Enclo so that you can access/update Monkey objects from it - e.g. $enclo->getMonkeys()? (yes/no)

Vous avez créer une relation bidirectional où vous pouvez récupérer des éléments de chaque côté de votre relation, assez pratique en réalité quand on veut récupérer tous les Monkeys d'un enclos !

Si vous avez activé cette option vous devriez avoir ça dans Enclo :

// Enclos.php

// ...

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Monkey", mappedBy="Enclo") // ici on inverse la relation pour avoir accès aux Monkeys depuis Enclo
     */
    private $monkeys;

    // Ici on initialise monkeys comme une collection, très important sinon ça ne marche pas !
    public function __construct()
    {
        $this->monkeys = new ArrayCollection();
    }

// ...

    /**
     * Récupération de la collection de tous les monkeys associés à cet enclos
     * @return Collection|Monkey[]
     */
    public function getMonkeys(): Collection
    {
        return $this->monkeys;
    }

    /**
    * Ajoute un monkey dans l'enclos
    */
    public function addMonkey(Monkey $monkey): self
    {
        if (!$this->monkeys->contains($monkey)) { // on vérifie si le monkey n'existe pas déjà
            $this->monkeys[] = $monkey; // on ajoute le monkey dans le tableau
            $monkey->setEnclos($this); // on paramètre l'enclos courant au singe qui a été ajouté
        }

        return $this;
    }

    /**
    * Supprime un singe dans l'enclos
    */
    public function removeMonkey(Monkey $monkey): self
    {
        if ($this->monkeys->contains($monkey)) { // Vérifie si le singe est bien présent
            $this->monkeys->removeElement($monkey); // on suprime l'élément du tableau
            // set the owning side to null (unless already changed)
            if ($monkey->getEnclo() === $this) { // Si le sionge a toujours l'enclos de paramétré
                $monkey->setEnclo(null); // on lui enlève
            }
        }

        return $this;
    }

Vous vouyez qu'il n'y a pas de vraiment de magie derrère tout ça, juste que les commandes make sont très pratique pour éviter de taper tout ça !

Essayez de bien comprendre ce que fais ce code, moins ça aura de secret pour vous, plus vous serez à l'aide avec ces relations.

Rassurez vous, c'est assez difficile pour les première relations, vous allez devoir recommencer plusieurs fois avant d'être tout à fait à l'aise avec ces relations !

Ajouter une relation

Si vous avez suivi la section précédente, vous devez vous douter que ce que l'on a vu ça va nous servir ici... et vous avez tout à fait raison !

Par exemple, si nous devons ajouter un singe dans un enclos, nous avons deux possibilités :

On passe par l'enclos :

// dans un controller, ceci est une méthode fictive d'exemple

public function setMonkeyEnclo(EntityManagerInterface $em, Request $request) {
    try {
        $monkeyId = $request->get('monkeyId'); // On récupère le monkey envoyé dans la requête
        $enclosId = $request->get('enclosId'); // On récupère l'enclo envoyé dans la requête

        $repositoryMonkey = $em->getRepository(Monkey::class);
        $rempositoryEnclo = $em->getRepository(Enclo::class);

        $monkey = $repositoryMonkey->findOneById($monkeyId);
        $enclo = $rempositoryEnclo->findOneById($monkeyId);

        $enclo->addMonkey($monkey);

        return $this->render('yourfabouloustemplate.html.twig', ['wateveryouwant' => 'really'])
    } catch (\Exception $e)  {
            return $this->render('honoerrortemplate.html.twig', ['whathappended' => '>:('])
    }
}

On passe par Monkey :

// dans un controller, ceci est une méthode fictive d'exemple

public function setEncloMonkey(EntityManagerInterface $em, Request $request) {
    try {
        $monkeyId = $request->get('monkeyId'); // On récupère le monkey envoyé dans la requête
        $enclosId = $request->get('enclosId'); // On récupère l'enclo envoyé dans la requête

        $repositoryMonkey = $em->getRepository(Monkey::class);
        $rempositoryEnclo = $em->getRepository(Enclo::class);

        $monkey = $repositoryMonkey->findOneById($monkeyId);
        $enclo = $rempositoryEnclo->findOneById($monkeyId);

        $monkey->setEnclo($enclo);

        return $this->render('yourfabouloustemplate.html.twig', ['wateveryouwant' => 'really'])
    } catch (\Exception $e)  {
            return $this->render('honoerrortemplate.html.twig', ['whathappended' => '>:('])
    }
}

Au final ces deux méthodes sont très similaires, tout dépends vraiment des informations que vous avez !

Vous pouvez aussi définir les relations à la création directement, ça marche aussi !

Récupérer les éléments liés

Les éléments liés sont automatiquement récupérés à la requête ! Vous avez donc juste à utiliser les getters pour récupérer les informations :

$enclo = $monkey->getEnclo(); //   et hop on récupère l'enclo avec toutes ses propriétés

// ...

$monkeys = $enclo->getMonkeys(); // et hop on récupères les singes avec toutes leur prorpriétés !

Conclusion

Ici nous avons appris à utiliser les différentes façon de mettre à jour une relation d'une entité, ainsi que comprendre comment elles sont créer par le maker.

Il est maintenant temps de mettre tout ça en pratique 😏

Envie de discuter du contenu ?

logo twitter @GarnierKristen