Bonjour, je suis sur le tuto de symfony 3 dans la partie Les relations entre entités avec Doctrine2 :
J'essaie d'affiché une image mais voici l'erreur :
Voici Advert.php :
<?php
namespace OC\PlatformBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Table(name="oc_advert")
* @ORM\Entity(repositoryClass="OC\PlatformBundle\Repository\AdvertRepository")
*/
class Advert
{
/**
* @ORM\OneToOne(targetEntity="OC\PlatformBundle\Entity\Image", cascade={"persist"})
*/
private $image;
/**
* Set image
*
* @param \OC\PlatformBundle\Entity\Image $image
*
* @return Advert
*/
public function setImage(\OC\PlatformBundle\Entity\Image $image = null)
{
$this->image = $image;
return $this;
}
/**
* Get image
*
* @return \OC\PlatformBundle\Entity\Image
*/
public function getImage()
{
return $this->image;
}
}
AdvertController.php :
// On récupère l'EntityManager
$em = $this->getDoctrine()->getManager();
// Création de l'entité
$advert = new Advert();
$advert->setTitle('Recherche développeur Symfony.');
$advert->setAuthor('Alexandre');
$advert->setContent("Nous recherchons un développeur Symfony débutant sur Lyon. Blabla…");
// Création de l'entité Image
$image = new Image();
$image->setUrl('//sdz-upload.s3.amazonaws.com/prod/upload/job-de-reve.jpg');
$image->setAlt('Job de rêve');
// On lie l'image à l'annonce
$advert->setImage($image);
// Étape 1 : On « persiste » l'entité
$em->persist($advert);
// Étape 2 : On « flush » tout ce qui a été persisté avant
$em->flush();
// Reste de la méthode qu'on avait déjà écrit
et ma vue view.html.twig :
<div style="float: left; margin-right: 1em;">
{# On vérifie qu'une image soit bien associée à l'article #}
<img src="{{ advert.image.url }}" alt="{{ advert.image.alt }}" height="60">
</div>
J'ai essayé de trouver le probleme mais impossible...
(j'ai essayé avec une "vraie" url => <img src="blabla.png" alt="blubli">et ça fonctionne)
Pour des raisons qui m'échappent, il arrive que les relations OneToOne ne soient pas persistées en cascade, ce qui fait ici que advert.image est nul (comme le dit très bien l'erreur, d'ailleurs), donc effectivement, tenter d'afficher l'URL de rien, ça ne va pas
Vérifie dans un premier temps que les informations de ton image sont bien présentes dans ta base de données, et surtout si la colonne de clé étrangère est bien renseignée.
Je ne suis pas certain que ce soit ça, mais à vérifier car tu doit avoir une erreur dans ton AdvertController
// Étape 1 : On « persiste » l'entité
$em->persist($advert);
$em->persist($image);
// Étape 2 : On « flush » tout ce qui a été persisté avant
$em->flush();
Créer l'advert est une chose, mais si tu ne persist pas l'image elle ne sera pas crée Quant au fait que tu ais l'image en tapant l'url, cela viens du fait que ça ne passe pas par la DB mais par le chemin qui devrait être dans la DB directement
Tout à fait d'accord. Les points de suspension n'étaient pas ironiques, mais perplexes. Ce n'est pas le premier sujet que je vois pour des soucis de persistance en cascade sur des OneToOne, et j'avoue que je n'ai que rarement compris quel était le problème, faute de l'avoir personnellement eu à résoudre.
Je n'ai jamais utilisé ceci, probablement car j'en ai pas encore eu l’utilité. Il doit y avoir une solution toute simple mais va savoir la quelle... A la rigueur ce serait bien d'avoir Image.php.
La table oc_image de ta DB est vide ? Si oui alors il ne créé pas l'image, d'où l'erreur. Il faut donc trouver pourquoi il ne le fait pas (cascade={"persist"} qui ne fonctionne pas ?)
Cela signifie que rien n'est inséré quand tu créé advert, ce qui n'est pas normal comme l'a dit Ymox étant donné que tu as cascade={"persist"} dans ton Advert.php. Le but (si tu as bien suivi le tuto), c'est que cette instruction persist tout les éléments qui concernent ton advert, comme ton image. Or les informations concernant cette dernière ne sont pas inséré, quand de l'autre côté l'image est bien dans tes dossier. C'est pour cela qu'une url directe fonctionne mais pas quand tu passes par la base de données. As-tu bien une entity Image ? (question bête mais sait-on jamais). Je viens de relire ton code et tu as probablement oublié une ligne:
Sinon comme dit plus haut, essaie de modifier le controller et advert:
AdvertController.php
// Étape 1 : On « persiste » l'entité
$em->persist($advert);
$em->persist($image);
// Étape 2 : On « flush » tout ce qui a été persisté avant
$em->flush();
J'ai tout essayé mais rien à faire ça me mets toujours la même erreur... J'ai essayer de copier coller (les bonnes parties évidemment) de la correction du cours mais rien y fait...
J'ai vider les caches (prod et dev) et rien de mieux
Voici AdvertController :
<?php
// src/OC/PlatformBundle/Controller/AdvertController.php
namespace OC\PlatformBundle\Controller;
use OC\PlatformBundle\Entity\Advert;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class AdvertController extends Controller
{
public function indexAction($page)
{
if ($page < 1) {
throw new NotFoundHttpException('Page "'.$page.'" inexistante.');
}
// Notre liste d'annonce en dur
$listAdverts = array(
array(
'title' => 'Recherche développpeur Symfony',
'id' => 1,
'author' => 'Alexandre',
'content' => 'Nous recherchons un développeur Symfony débutant sur Lyon. Blabla…',
'date' => new \Datetime()),
array(
'title' => 'Mission de webmaster',
'id' => 2,
'author' => 'Hugo',
'content' => 'Nous recherchons un webmaster capable de maintenir notre site internet. Blabla…',
'date' => new \Datetime()),
array(
'title' => 'Offre de stage webdesigner',
'id' => 3,
'author' => 'Mathieu',
'content' => 'Nous proposons un poste pour webdesigner. Blabla…',
'date' => new \Datetime())
);
return $this->render('OCPlatformBundle:Advert:index.html.twig', array(
'listAdverts' => $listAdverts,
));
}
public function viewAction($id)
{
// On récupère le repository
$repository = $this->getDoctrine()
->getManager()
->getRepository('OCPlatformBundle:Advert')
;
// On récupère l'entité correspondante à l'id $id
$advert = $repository->find($id);
// $advert est donc une instance de OC\PlatformBundle\Entity\Advert
// ou null si l'id $id n'existe pas, d'où ce if :
if (null === $advert) {
throw new NotFoundHttpException("L'annonce d'id ".$id." n'existe pas.");
}
// Le render ne change pas, on passait avant un tableau, maintenant un objet
return $this->render('OCPlatformBundle:Advert:view.html.twig', array(
'advert' => $advert
));
}
public function addAction(Request $request)
{
// On récupère l'EntityManager
$em = $this->getDoctrine()->getManager();
// Création de l'entité
$advert = new Advert();
$advert->setTitle('Recherche développeur Symfony.');
$advert->setAuthor('Alexandre');
$advert->setContent("Nous recherchons un développeur Symfony débutant sur Lyon. Blabla…");
// Création de l'entité Image
$image = new Image();
$image->setUrl('//sdz-upload.s3.amazonaws.com/prod/upload/job-de-reve.jpg');
$image->setAlt('Job de rêve');
// On lie l'image à l'annonce
$advert->setImage($image);
// Étape 1 : On « persiste » l'entité
$em->persist($advert);
$em->persist($image);
// Étape 2 : On « flush » tout ce qui a été persisté avant
$em->flush();
// Reste de la méthode qu'on avait déjà écrit
if ($request->isMethod('POST')) {
$request->getSession()->getFlashBag()->add('notice', 'Annonce bien enregistrée.');
// Puis on redirige vers la page de visualisation de cettte annonce
return $this->redirectToRoute('oc_platform_view', array('id' => $advert->getId()));
}
// Si on n'est pas en POST, alors on affiche le formulaire
return $this->render('OCPlatformBundle:Advert:add.html.twig');
}
public function editAction($id, Request $request)
{
if ($request->isMethod('POST')) {
$request->getSession()->getFlashBag()->add('notice', 'Annonce bien modifiée.');
return $this->redirectToRoute('oc_platform_view', array('id' => 5));
}
$advert = array(
'title' => 'Recherche développpeur Symfony',
'id' => $id,
'author' => 'Alexandre',
'content' => 'Nous recherchons un développeur Symfony débutant sur Lyon. Blabla…',
'date' => new \Datetime()
);
return $this->render('OCPlatformBundle:Advert:edit.html.twig', array(
'advert' => $advert
));
}
public function deleteAction($id)
{
return $this->render('OCPlatformBundle:Advert:delete.html.twig');
}
public function menuAction($limit)
{
// On fixe en dur une liste ici, bien entendu par la suite on la récupérera depuis la BDD !
$listAdverts = array(
array('id' => 2, 'title' => 'Recherche développeur Symfony'),
array('id' => 5, 'title' => 'Mission de webmaster'),
array('id' => 9, 'title' => 'Offre de stage webdesigner')
);
return $this->render('OCPlatformBundle:Advert:menu.html.twig', array(
// Tout l'intérêt est ici : le contrôleur passe les variables nécessaires au template !
'listAdverts' => $listAdverts
));
}
}
et Advert.php
<?php
namespace OC\PlatformBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Table(name="oc_advert")
* @ORM\Entity(repositoryClass="OC\PlatformBundle\Repository\AdvertRepository")
*/
class Advert
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var \DateTime
*
* @ORM\Column(name="date", type="datetime")
*/
private $date;
/**
* @var string
*
* @ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* @var string
*
* @ORM\Column(name="author", type="string", length=255)
*/
private $author;
/**
* @var string
*
* @ORM\Column(name="content", type="string", length=255)
*/
private $content;
/**
* @ORM\Column(name="published", type="boolean")
*/
private $published = true;
/**
* @ORM\OneToOne(targetEntity="OC\PlatformBundle\Entity\Image", cascade={"persist"})
*/
private $image;
public function __construct()
{
// Par défaut, la date de l'annonce est la date d'aujourd'hui
$this->date = new \Datetime();
}
/**
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* @param \DateTime $date
*/
public function setDate($date)
{
$this->date = $date;
}
/**
* @return \DateTime
*/
public function getDate()
{
return $this->date;
}
/**
* @param string $title
*/
public function setTitle($title)
{
$this->title = $title;
}
/**
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* @param string $author
*/
public function setAuthor($author)
{
$this->author = $author;
}
/**
* @return string
*/
public function getAuthor()
{
return $this->author;
}
/**
* @param string $content
*/
public function setContent($content)
{
$this->content = $content;
}
/**
* @return string
*/
public function getContent()
{
return $this->content;
}
/**
* @param bool $published
*/
public function setPublished($published)
{
$this->published = $published;
}
/**
* @return bool
*/
public function getPublished()
{
return $this->published;
}
/**
* Set image
*
* @param \OC\PlatformBundle\Entity\Image $image
*
* @return Advert
*/
public function setImage(\OC\PlatformBundle\Entity\Image $image = null)
{
$this->image = $image;
return $this;
}
/**
* Get image
*
* @return \OC\PlatformBundle\Entity\Image
*/
public function getImage()
{
return $this->image;
}
}
Pas besoin de tout le Controller pour trouver l'erreur, juste de addAction
AnthonyBois a écrit:
J'ai vider les caches (prod et dev) et rien de mieux
Voici AdvertController :
<?php
// src/OC/PlatformBundle/Controller/AdvertController.php
namespace OC\PlatformBundle\Controller;
use OC\PlatformBundle\Entity\Advert;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class AdvertController extends Controller
{
public function addAction(Request $request)
{
// On récupère l'EntityManager
$em = $this->getDoctrine()->getManager();
// Création de l'entité
$advert = new Advert();
$advert->setTitle('Recherche développeur Symfony.');
$advert->setAuthor('Alexandre');
$advert->setContent("Nous recherchons un développeur Symfony débutant sur Lyon. Blabla…");
// Création de l'entité Image
$image = new Image();
$image->setUrl('//sdz-upload.s3.amazonaws.com/prod/upload/job-de-reve.jpg');
$image->setAlt('Job de rêve');
// On lie l'image à l'annonce
$advert->setImage($image);
// Étape 1 : On « persiste » l'entité
$em->persist($advert);
$em->persist($image);
// Étape 2 : On « flush » tout ce qui a été persisté avant
$em->flush();
// Reste de la méthode qu'on avait déjà écrit
if ($request->isMethod('POST')) {
$request->getSession()->getFlashBag()->add('notice', 'Annonce bien enregistrée.');
// Puis on redirige vers la page de visualisation de cettte annonce
return $this->redirectToRoute('oc_platform_view', array('id' => $advert->getId()));
}
// Si on n'est pas en POST, alors on affiche le formulaire
return $this->render('OCPlatformBundle:Advert:add.html.twig');
}
}
Je ne suis pas certain mais tu as oublié d'apporter une modification dans ton advert. Je te copie la fonction addAction en supprimant les commentaires (tout est aussi commenté sauf ce qui a été modifié). En gros j'ai ajouté une ligne et supprimé le $em->persist($image):
public function addAction(Request $request)
{
//$em = $this->getDoctrine()->getManager();
//$advert = new Advert();
//$advert->setTitle('Recherche développeur Symfony.');
//$advert->setAuthor('Alexandre');
//$advert->setContent("Nous recherchons un développeur Symfony débutant sur Lyon. Blabla…");
//$image = new Image();
//$image->setUrl('//sdz-upload.s3.amazonaws.com/prod/upload/job-de-reve.jpg');
//$image->setAlt('Job de rêve');
//advert->setImage($image);
$em = $this->getDoctrine()->getManager();
//$em->persist($advert);
//$em->persist($image);
//$em->flush();
//if ($request->isMethod('POST')) {
//$request->getSession()->getFlashBag()->add('notice', 'Annonce bien enregistrée.');
//return $this->redirectToRoute('oc_platform_view', array('id' => $advert->getId()));
//}
//return $this->render('OCPlatformBundle:Advert:add.html.twig');
}
Si cela ne fonctionne toujours pas, remet le $em->persist($image):
Il devrait régénérer les entities (getter et setter). Copie moi à nouveau les fichiers après avoir fait ça que je voie les changements
Normalement tu ne devrais pas trop avoir à toucher ce que génère Symfony, surtout pour ce que tu lui demande. Ah et tant que j'y suis, je te conseil d'espacer ton code, mettre toutes les functions à la suite sans saut de ligne rends le code moins lisible. A toi de trouver tes méthodes qui te permettrons de relire des blocs de code avec moins de difficulté
--------------------
EDIT: J'ai loupé un gros point dans ton controller, en fait il n'arrive pas à ajouter l'image car il ne connait pas l'entity. Régénrer les entities car je pense certaines sont fausses, mais tu as surtout oublié d'inclure ton entity Image.php dans le controller
<?php
namespace OC\PlatformBundle\Controller;
use OC\PlatformBundle\Entity\Advert;
//oubli de l'entity image
use OC\PlatformBundle\Entity\Image
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class AdvertController extends Controller
{
//modification de la fonction
public function addAction(Request $request)
{
// Création de l'entité Advert
$advert = new Advert();
$advert->setTitle('Recherche développeur Symfony.');
$advert->setAuthor('Alexandre');
$advert->setContent("Nous recherchons un développeur Symfony débutant sur Lyon. Blabla…");
// Création de l'entité Image
$image = new Image();
$image->setUrl('//sdz-upload.s3.amazonaws.com/prod/upload/job-de-reve.jpg');
$image->setAlt('Job de rêve');
// On lie l'image à l'annonce
$advert->setImage($image);
// On récupère l'EntityManager
$em = $this->getDoctrine()->getManager();
// Étape 1 : On « persiste » l'entité
$em->persist($advert);
//pas besoin de persist($image) car on a cascade={"persist"} dans l'entity
// Étape 2 : On déclenche l'enregistrement
$em->flush();
// Reste de la méthode qu'on avait déjà écrit
if ($request->isMethod('POST')) {
$request->getSession()->getFlashBag()->add('notice', 'Annonce bien enregistrée.');
// Puis on redirige vers la page de visualisation de cettte annonce
return $this->redirectToRoute('oc_platform_view', array('id' => $advert->getId()));
}
// Si on n'est pas en POST, alors on affiche le formulaire
return $this->render('OCPlatformBundle:Advert:add.html.twig');
}
}
J'ai ajouté un use en haut et modifié la function addAction.
Ce serais dommage d'abandonner après avoir fait tout ce chemin Mais comme dans tout langage, les erreurs les plus compliquées à trouver sont les plus simples. Il faut juste trouver mais sinon tu as déjà réussit a faire plein de choses donc n'abandonne pas
Essaie de vider les caches (prod et dev) et de lire le poste de Ymox, ce sont des possibilités d'erreurs que tu pourras essayer de corriger facilement.
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
</radiax>
</radiax>
</radiax>
</radiax>
</radiax>
</radiax>
</radiax>
</radiax>
</radiax>
</radiax>
</radiax>
</radiax>