IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Symfony PHP Discussion :

Symfony 6: Créer un link d'image depuis sa collection dans Twig ?


Sujet :

Symfony PHP

  1. #1
    Membre actif
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    1 092
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 1 092
    Points : 268
    Points
    268
    Par défaut Symfony 6: Créer un link d'image depuis sa collection dans Twig ?
    Bonjour à tous,

    J'essaie en vain d'obtenir la première itération d'une image pour créer un link dans Twig :

    L'entité "images" est en relation avec "plats" et tout fonctionne à merveille au niveau de la bdd...
    les dump ramènent bien les données correspondantes

    J'ai essayé d'abord à l'ancienne avec un tableau :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <img class="thumbnail" src="{{asset('assets/uploads/plats/mini/300x300-'~ plat.images[0].name)}}" alt="{{plat.name}}">
    cela me donnait une erreur

    J'ai ensuite essayé avec :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <img class="thumbnail" src="{{asset('assets/uploads/plats/mini/300x300-'~ plat->getImages()->first().name)}}" alt="{{plat.name}}">
    pour accéder à l'info de la collection mais ça ne marche pas non plus, erreur de syntaxe ?

    Merci pour vos réponses

  2. #2
    Membre confirmé
    Homme Profil pro
    Autre
    Inscrit en
    Juillet 2021
    Messages
    319
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Juillet 2021
    Messages : 319
    Points : 640
    Points
    640
    Par défaut
    Bonjour,

    Quel est le message d'erreur avec le premier code ?
    Peux t-on voir un exemple du dump des données ?

    Le dossier assets n'est pas publique et son contenu n'est pas accessible, tes liens ne pourront pas fonctionner.
    Tes images devraient être situées dans le dossier public si tu n'utilises pas Webpack.

  3. #3
    Membre actif
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    1 092
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 1 092
    Points : 268
    Points
    268
    Par défaut
    Bonjour et merci d'avoir répondu

    Le message d'erreur est : An exception has been thrown during the rendering of a template ("Warning: Undefined array key "plats""), d'autant plus bizarre que tous les autres champs du template font référence à "plat" et sont bien rendus.

    Je ne peux fournir de dump une fois dans Twig car cela me fait planter le rendering avec un message de maximum memory usage exhausted... alors que le dump dans le controller (qui lui marche) renvoie bien la liste d'images de l'entité plats...

    Les noms des images sont aussi bien enregistrées dans la table "images" et chacune correctement reliée à l'id du 'plat' correspondant...

    Cela me laisse à penser que la façon d'interroger l'entité "plat.images[0]" pour avoir la première image de la collection dans le link n'est pas la bonne ...

    Concernant le dump impossible dans Twig : Faut il effectuer une configuration spéciale ?

    Merci beaucoup

    Controller PlatsController:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    <?php
     
    namespace App\Controller;
     
    use App\Entity\Images;
    use App\Entity\Plats;
    use App\Form\PlatsType;
    use App\Repository\PlatsRepository;
    use App\Service\PicturesService;
    use Doctrine\ORM\EntityManagerInterface;
    use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\Routing\Annotation\Route;
    use Symfony\Component\String\Slugger\SluggerInterface;
    use Symfony\Component\Validator\Constraints\Length;
     
    #[Route('admin/plats')]
    class PlatsController extends AbstractController
    {
        #[Route('/', name: 'plats_index', methods: ['GET'])]
        public function index(PlatsRepository $platsRepository): Response
        {
            return $this->render('admin/plats/index.html.twig', [
                'plats' => $platsRepository->findAll(),
            ]);
        }
     
        #[Route('/ajouter', name: 'plats_new', methods: ['GET', 'POST'])]
        public function new(Request $request, EntityManagerInterface $em, PicturesService $pictureService, SluggerInterface $slugger): Response
        {
            $plat = new Plats();
            $form = $this->createForm(PlatsType::class, $plat);
            $form->handleRequest($request);
     
            if ($form->isSubmitted() && $form->isValid()) {
     
                //Génération du slug
                // $slug=$slugger->slug($plat->getName());
                // $plat->setSlug($slug);
     
                //Récupération des images
                $images = $form->get('images')->getData();
     
                //Compteur images          
                $i = 0;
     
                foreach ($images as $image) {
                    $i++;
                    //dossier de destination des images importées
                    $folder = 'plats';
     
                    //Appel service d'ajout d'images
                    $fichier = $pictureService->add($image, $folder, 300, 300);
     
                    $img = new Images();
     
                    $img->setName($fichier);
                    $img->setTitre($plat->getName() . '_' . $i);
                    $plat->addImage($img);        
                }
     
     
                $em->persist($plat);
                $em->flush();
     
                $this->addFlash('alert alert-success', 'Plat ajouté avec succès !.');
                return $this->redirectToRoute('plats_index', [], Response::HTTP_SEE_OTHER);
            }
     
            return $this->render('admin/plats/new.html.twig', [
                'plat' => $plat,
                'form' => $form,
            ]);
        }
     
        #[Route('/{id}', name: 'plats_show', methods: ['GET'])]
        public function show(Plats $plat): Response
        {
            return $this->render('admin/plats/show.html.twig', [
                'plat' => $plat,
            ]);
        }
     
        #[Route('/{id}/modifier/', name: 'modifier_plat', methods: ['GET', 'POST'])]
        public function edit(Request $request, Plats $plat, EntityManagerInterface $em, SluggerInterface $slugger): Response
        {
            //Vérification si utilisateur peut éditer grâce au voter
            // $this->denyAccessUnlessGranted('[ROLE_ADMIN]');
     
            $form = $this->createForm(PlatsType::class, $plat);
            $form->handleRequest($request);
     
            if ($form->isSubmitted() && $form->isValid()) {
     
                // $slug=$slugger->slug($plat->getName());
     
                $em->persist($plat);
                $em->flush();
     
                $this->addFlash('alert alert-success', 'Plat modifié avec succès !.');
                return $this->redirectToRoute('plats_index', [], Response::HTTP_SEE_OTHER);
            }
     
            return $this->render('admin/plats/edit.html.twig', [
                'form' => $form->createView(),
                'plat' => $plat,
            ]);
        }
     
        #[Route('/{id}/effacer', name: 'plats_delete', methods: ['POST'])]
        public function delete(Request $request, Plats $plat, PlatsRepository $platsRepository): Response
        {
            if ($this->isCsrfTokenValid('delete' . $plat->getId(), $request->request->get('_token'))) {
                $platsRepository->remove($plat, true);
            }
     
            return $this->redirectToRoute('plats_index', [], Response::HTTP_SEE_OTHER);
        }
    }
    Entité Plats :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    <?php
     
    namespace App\Entity;
     
    use App\Entity\Trait\CreatedAtTrait;
    use App\Entity\Trait\SlugTrait;
    use App\Repository\PlatsRepository;
    use Doctrine\Common\Collections\ArrayCollection;
    use Doctrine\Common\Collections\Collection;
    use Doctrine\DBAL\Types\Types;
    use Doctrine\ORM\Mapping as ORM;
     
    #[ORM\Entity(repositoryClass: PlatsRepository::class)]
    class Plats
    {
        use CreatedAtTrait;
        use SlugTrait;
        #[ORM\Id]
        #[ORM\GeneratedValue]
        #[ORM\Column]
        private ?int $id = null;
     
        #[ORM\Column(length: 255)]
        private ?string $name = null;
     
        #[ORM\Column(type: Types::TEXT)]
        private ?string $description = null;
     
        #[ORM\Column]
        private ?int $price = null;
     
        #[ORM\ManyToOne(inversedBy: 'Plats')]
        #[ORM\JoinColumn(nullable: false)]
        private ?CategoriesPlats $categories = null;
     
        #[ORM\OneToMany(mappedBy: 'plats', targetEntity: Images::class, cascade: ['persist'], orphanRemoval: true)]
        private Collection $images;
     
        #[ORM\ManyToMany(targetEntity: Ingredients::class, inversedBy: 'Plats')]
        private Collection $ingredients;
     
        public function __construct()
        {
            $this->images = new ArrayCollection();
            $this->Created_At = new \DateTimeImmutable();
            $this->ingredients = new ArrayCollection();
        }
     
        public function getId(): ?int
        {
            return $this->id;
        }
     
        public function getName(): ?string
        {
            return $this->name;
        }
     
        public function setName(string $name): self
        {
            $this->name = $name;
     
            return $this;
        }
     
        public function getDescription(): ?string
        {
            return $this->description;
        }
     
        public function setDescription(string $description): self
        {
            $this->description = $description;
     
            return $this;
        }
     
        public function getPrice(): ?int
        {
            return $this->price;
        }
     
        public function setPrice(int $price): self
        {
            $this->price = $price;
     
            return $this;
        }
     
        public function getCategories(): ?CategoriesPlats
        {
            return $this->categories;
        }
     
        public function setCategories(?CategoriesPlats $categories): self
        {
            $this->categories = $categories;
     
            return $this;
        }
     
        /**
         * @return Collection<int, Images>
         */
        public function getImages(): Collection
        {
            return $this->images;
        }
     
        public function addImage(Images $image): self
        {
            if (!$this->images->contains($image)) {
                $this->images->add($image);
                $image->setPlats($this);
            }
     
            return $this;
        }
     
        public function removeImage(Images $image): self
        {
            if ($this->images->removeElement($image)) {
                // set the owning side to null (unless already changed)
                if ($image->getPlats() === $this) {
                    $image->setPlats(null);
                }
            }
     
            return $this;
        }
     
        /**
         * @return Collection<int, Ingredients>
         */
        public function getIngredients(): Collection
        {
            return $this->ingredients;
        }
     
        public function addIngredient(Ingredients $ingredient): self
        {
            if (!$this->ingredients->contains($ingredient)) {
                $this->ingredients->add($ingredient);
            }
     
            return $this;
        }
     
        public function removeIngredient(Ingredients $ingredient): self
        {
            $this->ingredients->removeElement($ingredient);
     
            return $this;
        }
    }
    Entité images :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    <?php
     
    namespace App\Entity;
     
    use App\Repository\ImagesRepository;
    use Doctrine\DBAL\Types\Types;
    use Doctrine\ORM\Mapping as ORM;
     
    #[ORM\Entity(repositoryClass: ImagesRepository::class)]
    class Images
    {
        #[ORM\Id]
        #[ORM\GeneratedValue]
        #[ORM\Column]
        private ?int $id = null;
     
        #[ORM\Column(length: 255)]
        private ?string $name = null;
     
        #[ORM\ManyToOne(inversedBy: 'images')]
        #[ORM\JoinColumn(nullable: false)]
        private ?Plats $Plats = null;
     
        #[ORM\Column(length: 255, nullable: true)]
        private ?string $titre = null;
     
        #[ORM\Column(type: Types::TEXT, nullable: true)]
        private ?string $description = null;
     
        #[ORM\Column(nullable: true)]
        private ?int $taille = null;
     
        public function getId(): ?int
        {
            return $this->id;
        }
     
        public function getName(): ?string
        {
            return $this->name;
        }
     
        public function setName(string $name): self
        {
            $this->name = $name;
     
            return $this;
        }
     
        public function getPlats(): ?Plats
        {
            return $this->Plats;
        }
     
        public function setPlats(?Plats $Plats): self
        {
            $this->Plats = $Plats;
     
            return $this;
        }
     
        public function getTitre(): ?string
        {
            return $this->titre;
        }
     
        public function setTitre(?string $titre): self
        {
            $this->titre = $titre;
     
            return $this;
        }
     
        public function getDescription(): ?string
        {
            return $this->description;
        }
     
        public function setDescription(?string $description): self
        {
            $this->description = $description;
     
            return $this;
        }
     
        public function getTaille(): ?int
        {
            return $this->taille;
        }
     
        public function setTaille(?int $taille): self
        {
            $this->taille = $taille;
     
            return $this;
        }
    }

  4. #4
    Membre confirmé
    Homme Profil pro
    Autre
    Inscrit en
    Juillet 2021
    Messages
    319
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Juillet 2021
    Messages : 319
    Points : 640
    Points
    640
    Par défaut
    Le message d'erreur ne semble pas correspondre à ton premier code (le message indique que tu essayes d'accéder à un élément de tableau avec la clé 'plat').

    A priori, la relation entre tes entités est correcte.
    La syntaxe plat.images[0] devrait fonctionner à condition que chaque plat ait bien au moins une image, es-tu sûr que c'est bien le cas ?
    A tester dans ton template twig :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    {% for plat in plats %} 
      Nom du plat : {{ plat.name }}
     
      {% if plat.images[0] is defined %}
        Première image : {{ plat.images[0].name }}
      {% else %}
        Aucune image pour ce plat !
      {% endif %}
    {% endfor %}

  5. #5
    Membre actif
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    1 092
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 1 092
    Points : 268
    Points
    268
    Par défaut
    J'ai mis votre boucle à la suite dans le code : le message est le même, que faire .? :

  6. #6
    Membre confirmé
    Homme Profil pro
    Autre
    Inscrit en
    Juillet 2021
    Messages
    319
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Juillet 2021
    Messages : 319
    Points : 640
    Points
    640
    Par défaut
    Le message doit indiquer le fichier et le numéro de la ligne où se déclenche l'erreur.
    La question à se poser est donc : quel est le code dans le template qui déclenche cette erreur ?

  7. #7
    Membre actif
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    1 092
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 1 092
    Points : 268
    Points
    268
    Par défaut
    L'erreur est provoquée apparemment car je ne peux utiliser "plat.images[0]" pour restreindre l'affichage à une seule image ...

    Ne pouvant pas utiliser de dump car il fait planter symfony je ne vois vraiment pas comment vérifier le tableau envoyé depuis platsController avec le nom "plats" !!!

    Vraisemblablement le tableau renvoyé ne contient pas la référence aux images de chaque plat, j'utilise le repository pour afficher la route "app_plats_index" avec un filtre, il faut peut être renvoyer la référence aux images dans ce tableau mais comment faire (un getImages() peut-être) ?

  8. #8
    Membre confirmé
    Homme Profil pro
    Autre
    Inscrit en
    Juillet 2021
    Messages
    319
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Juillet 2021
    Messages : 319
    Points : 640
    Points
    640
    Par défaut
    Peux tu partager le code de ton template pour essayer de reproduire ton erreur ?

  9. #9
    Membre actif
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    1 092
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 1 092
    Points : 268
    Points
    268
    Par défaut
    Le voici, merci pour votre aimable aide

    Ligne 38 et à partir de 50...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    {% extends 'base.html.twig' %}
     
    {% block title %}Liste des Plats
    {% endblock %}
     
    {% block body %}
     
    	<div class="content">
    		<h1 class="grandTitre">Liste des Plats</h1>
    		<a class="link-retour" href="{{path('dashboard')}}">Retourner au dashboard</a>
    		<button class="btn-creation">
    			<a href="{{ path('app_plats_ajouter') }}">Créer un plat</a>
    		</button>
     
    		<table class="table">
    			<thead>
    				<tr>
    					<th></th>
    					<th>Image</th>
    					<th>Nom</th>
    					<th>Catégorie</th>
    					<th>Description</th>
    					<th>Prix</th>
    					<th>Crée le :</th>
    				</tr>
    			</thead>
     
    			<tbody>
    				{% for plat in plats %}
     
    					<tr>
    						<td>
    							<a href="{{ path('app_modifier_plat', {'id': plat.id}) }}">
    								<i class="fa fa-folder-open" aria-hidden="true"></i>Ouvrir</a>
    						</td>
     
    						<td>
    							{# <img class="thumbnail" src="{{asset('/assets/uploads/plats/mini/300x300-'~ plat.images[0].name)}}" alt="{{plat.name}}"> #}
    						</td>
    						<td>
    							<strong>{{ plat.name }}</strong>
    						</td>
    						<td>
    							<p>{{plat.categories}}</p>
    						</td>
    						<td>{{ plat.description }}</td>
    						<td>{{ plat.price }}</td>
    						<td>{{ plat.Created_At ? plat.Created_At|date('d-m-Y H:i:s') : '' }}</td>
     
    						Nom du plat :
    						{{ plat.name }}
    {# 
    						{% if plat.images[0] is defined %}
    							Première image :
    							{{ plat.images[0].name }}
    						{% else %}
    							Aucune image pour ce plat !
    						{% endif %} #}
    					</tr>
    				</td>
    			</tbody>
    		</tr>
    	{% else %}
    		<tr>
    			<td colspan="7">Aucun enregistrement trouvé</td>
    		</tr>
    	{% endfor %}
    </tbody></table></div>{% endblock %}

  10. #10
    Membre confirmé
    Homme Profil pro
    Autre
    Inscrit en
    Juillet 2021
    Messages
    319
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Autre

    Informations forums :
    Inscription : Juillet 2021
    Messages : 319
    Points : 640
    Points
    640
    Par défaut
    L'erreur vient à priori de la majuscule en première lettre pour la propriété $Plats dans la classe Images.
    Essaye de suivre la même convention que pour les autres propriétés, corrige celle-ci en $plats sans majuscule et corrige les getter/setter associés.

  11. #11
    Membre actif
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    1 092
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 1 092
    Points : 268
    Points
    268
    Par défaut
    Merveilleux ! tout remarche !

    Et dire que pendant un moment je me posais la question si ça ne venait pas d'une erreur de frappe ...

    Merci beaucoup !!!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 5
    Dernier message: 03/05/2018, 18h31
  2. Réponses: 13
    Dernier message: 16/01/2015, 10h50
  3. Afficher des images depuis une table dans combobox
    Par sihammaster dans le forum VB.NET
    Réponses: 2
    Dernier message: 13/04/2010, 19h51
  4. Réponses: 2
    Dernier message: 13/03/2010, 16h03

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo