i use vich uploader bundle to display images added to my data base
here is my code
config.yml :
vich_uploader:
db_driver: orm
mappings:
cours_image:
uri_prefix: /images/cours
upload_destination: '%kernel.root_dir%/../web/images/cours'
inject_on_load: true
delete_on_update: false
delete_on_remove: true
namer: vich_uploader.namer_origname
the entity
<?php
namespace DataBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
use Symfony\Component\HttpFoundation\File\File;
/**
* CoursCode
*
* #ORM\Table(name="cours_code")
* #ORM\Entity
* #Vich\Uploadable
*/
class CoursCode
{
/**
* #var integer
*
* #ORM\Column(name="id_cours", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $idCours;
/**
* #var string
*
* #ORM\Column(name="titre_cours", type="string", length=50, nullable=false)
*/
private $titreCours;
/**
* #var string
*
* #ORM\Column(name="contenu_cours", type="text", length=65535, nullable=false)
*/
private $contenuCours;
/**
* NOTE: This is not a mapped field of entity metadata, just a simple property.
*
* #Vich\UploadableField(mapping="cours_image", fileNameProperty="imageName", size="imageSize")
* #Assert\File(maxSize="1200k",mimeTypes={"image/png", "image/jpeg", "image/pjpeg"})
*
* #var File
*/
private $imageFile;
/**
* #ORM\Column(type="string", length=255)
*
* #var string
*/
private $imageName;
/**
* #ORM\Column(type="integer", nullable=true)
*
* #var integer
*/
private $imageSize;
/**
* #ORM\Column(type="datetime")
*
* #var \DateTime
*/
private $updatedAt;
/**
* If manually uploading a file (i.e. not using Symfony Form) ensure an instance
* of 'UploadedFile' is injected into this setter to trigger the update. If this
* bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
* must be able to accept an instance of 'File' as the bundle will inject one here
* during Doctrine hydration.
*
* #param File|\Symfony\Component\HttpFoundation\File\UploadedFile $image
*
* #return CoursCode
*/
public function setImageFile(File $image = null)
{
$this->imageFile = $image;
if ($image) {
// It is required that at least one field changes if you are using doctrine
// otherwise the event listeners won't be called and the file is lost
$this->updatedAt = new \DateTimeImmutable();
}
return $this;
}
/**
* #return File|null
*/
public function getImageFile()
{
return $this->imageFile;
}
/**
* #param string $imageName
*
* #return CoursCode
*/
public function setImageName($imageName)
{
$this->imageName = $imageName;
return $this;
}
/**
* #return string|null
*/
public function getImageName()
{
return $this->imageName;
}
/**
* #param integer $imageSize
*
* #return CoursCode
*/
public function setImageSize($imageSize)
{
$this->imagesize = $imageSize;
return $this;
}
/**
* #return integer|null
*/
public function getImageSize()
{
return $this->imageSize;
}
/**
* #return int
*/
public function getIdCours()
{
return $this->idCours;
}
/**
* #param int $idCours
*/
public function setIdCours($idCours)
{
$this->idCours = $idCours;
}
/**
* #return string
*/
public function getTitreCours()
{
return $this->titreCours;
}
/**
* #param string $titreCours
*/
public function setTitreCours($titreCours)
{
$this->titreCours = $titreCours;
}
/**
* #return string
*/
public function getContenuCours()
{
return $this->contenuCours;
}
/**
* #param string $contenuCours
*/
public function setContenuCours($contenuCours)
{
$this->contenuCours = $contenuCours;
}
}
the twig:
{% for c in cours %}
<div class="col-md-6 col-sm-12">
<article class="cp-taxi-holder cp-deals-holder">
<figure class="cp-thumb">
<img src=" {{ vich_uploader_asset(c, 'imageFile') }}" />
</figure>
<div class="cp-text">
<h3> {{ c.titreCours}}</h3>
<ul class="cp-meta-listed">
<li>Niveau de difficulté <span>moyen</span></li>
</ul>
Voir les lessons
</div>
</article>
</div>
{% endfor %} }}
the controller :
public function AfficheCoursFrontAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$cours = $em->getRepository('DataBundle:CoursCode')->findAll();
/**
* #var $paginator \knp\Component\Pager\paginator
*/
$paginator = $this->get('knp_paginator');
$result = $paginator->paginate(
$cours,
$request->query->getInt('page',1) /*page number*/,
$request->query->getInt('limit',4) /*limit per page*/
);
the form:
class AjoutCoursType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('titreCours')
->add('contenuCours')
->add('imageFile', VichImageType::class, [
'required' => false,])
->add('Ajout',SubmitType::class)
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'DataBundle\Entity\CoursCode'
));
}
symfony is reading the file but doesn't show it
i can't find the problem
The first thing you should do is to inspect your html render and search for the image, then check if src is correct. If the link is correct it's probably a permission error and you should look at the permissions applied to the upload folder web/images/cours.
Related
In my Symfony 3.4 project (vich/uploader-bundle: "^1.4"), I need to upload 3 kinds of files and for two of them it's work, but for the third even if i use the same process it doesn't work...? When the form is submitted, i get this exception:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'document_name' cannot be null
when i dumped, i can see that my Setter "vichuploader document name" not work and can't persisted.
This is the context:
*Everythings is ok on my local version...Files are uploaded but on my production version it's doesn't work.
*I have one Entity (NoteFrais) with OneToOne relation with another Entity (Justificatif).
*The Justificatif entity has the #vich\uploadable annotation
I followed the documentation, read many tuto, ask question on stackverflow, cleared cache and updated doctrine schema many times, tried many things...
******config.yml********
parameters:
locale: fr
app.path.logos: /uploads/logos
app.path.imports: /uploads/imports
app.path.documents: /uploads/documents
vich_uploader:
db_driver: orm
mappings:
logo:
uri_prefix: '%app.path.logos%'
upload_destination: '%kernel.root_dir%/../web%app.path.logos%' //========IT'S WORK FINE FOR THIS ONE==========//
namer: vich_uploader.namer_uniqid
inject_on_load: false
delete_on_update: true
delete_on_remove: true
import:
uri_prefix: '%app.path.imports%'
upload_destination: '%kernel.root_dir%/../web%app.path.imports%' //=========IT'S WORK FINE THIS ONE=========//
namer: vich_uploader.namer_uniqid
# inject_on_load: true important!!
inject_on_load: false
delete_on_update: true
delete_on_remove: true
document:
uri_prefix: '%app.path.documents%'
upload_destination: '%kernel.root_dir%/../web%app.path.documents%'
namer: vich_uploader.namer_uniqid
# inject_on_load: true important!!
inject_on_load: false
delete_on_update: true
delete_on_remove: true
******JustificatifType*******
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('justificatifFile', FileType::class, array( //========= I TRIED WITH FILETYPE OR VICHFILETYPE =======//
//'data_class' => null, //======== NOTE:USALLY I USE TO FILETYPE AND IT'S WORK FINE ==============//
'label' => false,
'required' => true,
'attr' => array(
'class' => 'NoteFraisBootstrapFileInput',
'type' => 'file',
'placeholder' => 'Selectionner un justificatif (jpeg, png, jpg, pdf)',
'data-preview-file-type' => 'text',
'data-allowed-file-extensions' => '["jpeg", "png", "jpg", "pdf"]',
)
));
}
******NoteFraisType**********
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
//=======OTHERS FIELDS===========//
->add('justificatif', JustificatifType::class, array(
'required' => false));
}
*****Justificatif.php (Entity)*****
<?php
namespace MKG\MystiBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* Justificatif
*
* #ORM\Table(name="justificatif")
* #ORM\Entity(repositoryClass="MKG\MystiBundle\Repository\JustificatifRepository")
* #vich\Uploadable
*/
class Justificatif
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* NOTE: This is not a mapped field of entity metadata, just a simple property.
*
* #Vich\UploadableField(mapping="document", fileNameProperty="documentName")
*
* #var File
*/
private $justificatifFile;
/**
* #ORM\Column(type="string", length=255)
*
* #var string
*/
private $documentName;
/**
* #ORM\Column(type="datetime")
*
* #var \DateTime
*/
private $updatedAt;
/**
* Constructor
*/
public function __construct()
{
$this->updatedAt = new \DateTime();
}
/**
* If manually uploading a file (i.e. not using Symfony Form) ensure an instance
* of 'UploadedFile' is injected into this setter to trigger the update. If this
* bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
* must be able to accept an instance of 'File' as the bundle will inject one here
* during Doctrine hydration.
*
* #param File|UploadedFile $justificatif
*/
public function setJustificatifFile(File $justificatif = null)
{
$this->justificatifFile = $justificatif;
if ($justificatif) {
$this->updatedAt = new \DateTime('now');
}
}
/**
* #return File|null
*/
public function getJustificatifFile()
{
return $this->justificatifFile;
}
/**
*
* #param $documentName
*
* #return $this
*/
public function setDocumentName($documentName)
{
$this->documentName = $documentName;
return $this;
}
/**
* #return string|null
*/
public function getDocumentName()
{
return $this->documentName;
}
/**
* Set updatedAt
*
* #param \DateTime $updatedAt
*
* #return Justificatif
*/
public function setUpdatedAt($updatedAt)
{
$this->updatedAt = $updatedAt;
return $this;
}
/**
* Get updatedAt
*
* #return \DateTime
*/
public function getUpdatedAt()
{
return $this->updatedAt;
}
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
}
*******NoteFrais (Entity)*********
<?php
namespace MKG\MystiBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* NoteFrais
*
* #ORM\Table(name="note_frais")
* #ORM\Entity(repositoryClass="MKG\MystiBundle\Repository\NoteFraisRepository")
*/
class NoteFrais
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="MKG\MystiBundle\Entity\Mission", cascade={"persist"})
* #ORM\JoinColumn(name="mission_id", referencedColumnName="id", onDelete="CASCADE", nullable=true)
*/
private $mission;
/**
* #ORM\ManyToOne(targetEntity="MKG\MystiBundle\Entity\CodeComptable", cascade={"persist"})
* #ORM\JoinColumn(name="compte_comptable_id", referencedColumnName="id", onDelete="SET NULL", nullable=true)
*/
private $compteComptable;
/**
* #var string
*
* #ORM\Column(name="montant_defraiement_max", type="string", length=255, nullable=false)
*/
private $montantDefraiementMax;
/**
* #var string
*
* #ORM\Column(name="refacturation_client", type="string", length=255, nullable=true)
*/
private $refacturationClient;
/**
* #var string
*
* #ORM\Column(name="total_defraiement", type="string", length=255, nullable=true)
*/
private $totalDefraiement;
/**
* #var string
*
* #ORM\Column(name="total_refacturation", type="string", length=255, nullable=true)
*/
private $totalRefacturation;
/**
* #var string
*
* #ORM\Column(name="compte_avances_et_acomptes", type="string", length=255, nullable=true)
*/
private $compteAvancesEtAcomptes;
/**
* #var string
*
* #ORM\Column(name="admin_current_user", type="string", length=255, nullable=true)
*/
private $currentUser;
/**
* #var string
*
* #ORM\Column(name="code_affaire", type="string", length=255, nullable=true)
*/
private $codeAffaire;
/**
* #var string
*
* #ORM\Column(name="etat", type="string", length=255, nullable=true)
*/
private $etat;
/**
* #ORM\OneToOne(targetEntity="Justificatif", cascade={"persist"})
* #ORM\JoinColumn(name="justificatif_id", referencedColumnName="id", onDelete="CASCADE", nullable=true)
*/
private $justificatif;
/**
* #var \DateTime
*
* #ORM\Column(name="dateCreation", type="datetime")
*/
private $dateCreation;
public function __construct() {
$this->dateCreation = new \DateTime;
$this->etat = "0";
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set montantDefraiementMax
*
* #param string $montantDefraiementMax
*
* #return NoteFrais
*/
public function setMontantDefraiementMax($montantDefraiementMax)
{
$this->montantDefraiementMax = $montantDefraiementMax;
return $this;
}
/**
* Get montantDefraiementMax
*
* #return string
*/
public function getMontantDefraiementMax()
{
return $this->montantDefraiementMax;
}
/**
* Set refacturationClient
*
* #param string $refacturationClient
*
* #return NoteFrais
*/
public function setRefacturationClient($refacturationClient)
{
$this->refacturationClient = $refacturationClient;
return $this;
}
/**
* Get refacturationClient
*
* #return string
*/
public function getRefacturationClient()
{
return $this->refacturationClient;
}
/**
* Set compteAvancesEtAcomptes
*
* #param string $compteAvancesEtAcomptes
*
* #return NoteFrais
*/
public function setCompteAvancesEtAcomptes($compteAvancesEtAcomptes)
{
$this->compteAvancesEtAcomptes = $compteAvancesEtAcomptes;
return $this;
}
/**
* Get compteAvancesEtAcomptes
*
* #return string
*/
public function getCompteAvancesEtAcomptes()
{
return $this->compteAvancesEtAcomptes;
}
/**
* Set currentUser
*
* #param string $currentUser
*
* #return NoteFrais
*/
public function setCurrentUser($currentUser)
{
$this->currentUser = $currentUser;
return $this;
}
/**
* Get currentUser
*
* #return string
*/
public function getCurrentUser()
{
return $this->currentUser;
}
/**
* Set codeAffaire
*
* #param string $codeAffaire
*
* #return NoteFrais
*/
public function setCodeAffaire($codeAffaire)
{
$this->codeAffaire = $codeAffaire;
return $this;
}
/**
* Get codeAffaire
*
* #return string
*/
public function getCodeAffaire()
{
return $this->codeAffaire;
}
/**
* Set etat
*
* #param string $etat
*
* #return NoteFrais
*/
public function setEtat($etat)
{
$this->etat = $etat;
return $this;
}
/**
* Get etat
*
* #return string
*/
public function getEtat()
{
return $this->etat;
}
/**
* Set dateCreation
*
* #param \DateTime $dateCreation
*
* #return NoteFrais
*/
public function setDateCreation($dateCreation)
{
$this->dateCreation = $dateCreation;
return $this;
}
/**
* Get dateCreation
*
* #return \DateTime
*/
public function getDateCreation()
{
return $this->dateCreation;
}
/**
* Set mission
*
* #param \MKG\MystiBundle\Entity\Mission $mission
*
* #return NoteFrais
*/
public function setMission(\MKG\MystiBundle\Entity\Mission $mission = null)
{
$this->mission = $mission;
return $this;
}
/**
* Get mission
*
* #return \MKG\MystiBundle\Entity\Mission
*/
public function getMission()
{
return $this->mission;
}
/**
* Set compteComptable
*
* #param \MKG\MystiBundle\Entity\CodeComptable $compteComptable
*
* #return NoteFrais
*/
public function setCompteComptable(\MKG\MystiBundle\Entity\CodeComptable $compteComptable = null)
{
$this->compteComptable = $compteComptable;
return $this;
}
/**
* Get compteComptable
*
* #return \MKG\MystiBundle\Entity\CodeComptable
*/
public function getCompteComptable()
{
return $this->compteComptable;
}
/**
* Set justificatif
*
* #param \MKG\MystiBundle\Entity\Justificatif $justificatif
*
* #return NoteFrais
*/
public function setJustificatif(\MKG\MystiBundle\Entity\Justificatif $justificatif = null)
{
$this->justificatif = $justificatif;
return $this;
}
/**
* #return File
*/
public function getJustificatif()
{
return $this->justificatif;
}
/**
* Set totalDefraiement
*
* #param string $totalDefraiement
*
* #return NoteFrais
*/
public function setTotalDefraiement($totalDefraiement)
{
$this->totalDefraiement = $totalDefraiement;
return $this;
}
/**
* Get totalDefraiement
*
* #return string
*/
public function getTotalDefraiement()
{
return $this->totalDefraiement;
}
/**
* Set totalRefacturation
*
* #param string $totalRefacturation
*
* #return NoteFrais
*/
public function setTotalRefacturation($totalRefacturation)
{
$this->totalRefacturation = $totalRefacturation;
return $this;
}
/**
* Get totalRefacturation
*
* #return string
*/
public function getTotalRefacturation()
{
return $this->totalRefacturation;
}
}
********* newAction in NoteFraisController *********
/**
* Creates a new noteFrais entity.
*
*/
public function newAction(Request $request)
{
// === RECUPERE LA MISSION
$em = $this->getDoctrine()->getManager();
$mission = $em->getRepository('MKGMystiBundle:Mission')->findOneBy(array('id' => $request->get('idMission')));
$lignesNoteFrais = $em->getRepository('MKGMystiBundle:NoteFrais')->findBy(array('mission' => $mission->getId()));
$noteFrais = new Notefrais();
$form = $this->createForm('MKG\MystiBundle\Form\NoteFraisType', $noteFrais);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
//$noteFrais->setMission($mission);
$em = $this->getDoctrine()->getManager();
$em->persist($noteFrais);
//dump($noteFrais);die();
$em->flush();
$this->addFlash('notice', 'Une ligne a été ajouté à la note de frais!');
return $this->redirect($request->getUri());
}
return $this->render('#MKGMysti/Notefrais/new.html.twig', array(
'lignesNoteFrais' => $lignesNoteFrais,
'mission' => $mission,
'noteFrais' => $noteFrais,
'form' => $form->createView(),
));
}
Thank you very much your time!!!!
I just make my 2 entity, one is Article and one is Commento, that are comments.
I want a comment form in every single article, so I created the 2 entity, the action in the controller, and the template.
ARTICLE ENTITY
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Article
*
* #ORM\Table()
* #ORM\HasLifecycleCallbacks
* #ORM\Entity
*/
class Article
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="titolo", type="string", length=255)
*/
private $titolo;
/**
* #var string
*
* #ORM\Column(name="autore", type="string", length=255)
*/
private $autore;
/**
* #var string
*
* #ORM\Column(name="testo", type="text")
*/
private $testo;
/**
* #var string
*
* #ORM\Column(name="categoria", type="string", length=100)
*/
private $categoria;
/**
* #var string $image
* #Assert\File( maxSize = "1024k", mimeTypesMessage = "Perfavore inserisci un'immagine valida!")
* #ORM\Column(name="image", type="string", length=255, nullable=true)
*/
private $image;
/**
* #var date
*
* #ORM\Column(name="data", type="date")
*/
public $data;
/**
* #ORM\OneToMany(targetEntity="Commento", mappedBy="commento")
*/
protected $commento;
public function __construct()
{
$this->commento = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set titolo
*
* #param string $titolo
*
* #return Article
*/
public function setTitolo($titolo)
{
$this->titolo = $titolo;
return $this;
}
/**
* Get titolo
*
* #return string
*/
public function getTitolo()
{
return $this->titolo;
}
/**
* Set autore
*
* #param string $autore
*
* #return Article
*/
public function setAutore($autore)
{
$this->autore = $autore;
return $this;
}
/**
* Get autore
*
* #return string
*/
public function getAutore()
{
return $this->autore;
}
/**
* Set testo
*
* #param string $testo
*
* #return Article
*/
public function setTesto($testo)
{
$this->testo = $testo;
return $this;
}
/**
* Get testo
*
* #return string
*/
public function getTesto()
{
return $this->testo;
}
/**
* Set image
*
* #param string $image
*/
public function setImage($image)
{
$this->image = $image;
}
/**
* Get image
*
* #return string
*/
public function getImage()
{
return $this->image;
}
public function getFullImagePath() {
return null === $this->image ? null : $this->getUploadRootDir(). $this->image;
}
protected function getUploadRootDir() {
// the absolute directory path where uploaded documents should be saved
return $this->getTmpUploadRootDir().$this->getId()."/";
}
protected function getTmpUploadRootDir() {
// the absolute directory path where uploaded documents should be saved
return __DIR__ . '/../../../web/imgArticoli/';
}
/**
* #ORM\PrePersist()
* #ORM\PreUpdate()
*/
public function uploadImage() {
// the file property can be empty if the field is not required
if (null === $this->image) {
return;
}
if(!$this->id){
$this->image->move($this->getTmpUploadRootDir(), $this->image->getClientOriginalName());
}else{
$this->image->move($this->getUploadRootDir(), $this->image->getClientOriginalName());
}
$this->setImage($this->image->getClientOriginalName());
}
/**
* #ORM\PostPersist()
*/
public function moveImage()
{
if (null === $this->image) {
return;
}
if(!is_dir($this->getUploadRootDir())){
mkdir($this->getUploadRootDir());
}
copy($this->getTmpUploadRootDir().$this->image, $this->getFullImagePath());
unlink($this->getTmpUploadRootDir().$this->image);
}
/**
* Set data
*
* #param \DateTime $data
*
* #return Article
*/
public function setData($data)
{
$this->data = $data;
return $this;
}
/**
* Get data
*
* #return \DateTime
*/
public function getData()
{
return $this->data;
}
/**
* Set categoria
*
* #param string $categoria
*
* #return Article
*/
public function setCategoria($categoria)
{
$this->categoria = $categoria;
return $this;
}
/**
* Get categoria
*
* #return string
*/
public function getCategoria()
{
return $this->categoria;
}
/**
* Add commento
*
* #param \AppBundle\Entity\Commento $commento
*
* #return Article
*/
public function addCommento(\AppBundle\Entity\Commento $commento)
{
$this->commento[] = $commento;
return $this;
}
/**
* Remove commento
*
* #param \AppBundle\Entity\Commento $commento
*/
public function removeCommento(\AppBundle\Entity\Commento $commento)
{
$this->commento->removeElement($commento);
}
/**
* Get commento
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getCommento()
{
return $this->commento;
}
}
COMMENTO ENTITY
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Commento
*
* #ORM\Table()
* #ORM\HasLifecycleCallbacks
* #ORM\Entity
*/
class Commento
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="nome", type="string", length=255)
*/
private $nome;
/**
* #var string
*
* #ORM\Column(name="testo", type="text")
*/
private $testo;
/**
* #var datetime
*
* #ORM\Column(name="data", type="datetime")
*/
public $data;
/**
*#ORM\ManyToOne(targetEntity="Article",inversedBy="commenti")
* #ORM\JoinColumn(name="article_id",referencedColumnName="id")
*/
protected $article;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set nome
*
* #param string $nome
*
* #return Commento
*/
public function setNome($nome)
{
$this->nome = $nome;
return $this;
}
/**
* Get nome
*
* #return string
*/
public function getNome()
{
return $this->nome;
}
/**
* Set testo
*
* #param string $testo
*
* #return Commento
*/
public function setTesto($testo)
{
$this->testo = $testo;
return $this;
}
/**
* Get testo
*
* #return string
*/
public function getTesto()
{
return $this->testo;
}
/**
* Set data
*
* #param \DateTime $data
*
* #return Commento
*/
public function setData($data)
{
$this->data = $data;
return $this;
}
/**
* Get data
*
* #return \DateTime
*/
public function getData()
{
return $this->data;
}
/**
* Set article
*
* #param \AppBundle\Entity\Article $article
* #return Commento
*/
public function setArticle(\AppBundle\Entity\Article $article=null)
{
$this->article = $article;
return $this;
}
/**
* Get article
*
* #return \AppBundle\Entity\Article
*/
public function getArticle()
{
return $this->article;
}
}
ACTIONS IN THE CONTROLLER
public function singlearticleAction(Request $request, $id)
{
//Codice di singlearticle
$art = $this->getDoctrine()->getEntityManager();
$article = $art->getRepository('AppBundle:Article')->find($id);
if (!$article)
{
throw $this->createNotFoundException('Non riesco a trovare questo articolo!');
}
//Fin qui
$commento = new Commento();
$commento->setData(new \DateTime('now'));
$form = $this->createForm(new CommentoType($article), $commento);
$request = $this->getRequest();
$form->handleRequest($request);
if ($form->isValid())
{
if ($article)
{
$commento->setArticle($article);
}
$em = $this->getDoctrine()->getManager();
try
{
$em->persist($commento);
$em->flush();
return $this->redirect('singlearticle');
} catch (\Exception $e)
{
$form->addError(new FormError('errore nel database'));
}
}
return $this->render('default/singlearticle.html.twig', array(
'article' => $article,
'commento' => $commento,
'form' => $form->createView()));
}
public function inserisci_commentoAction(Request $request)/* ROTTA "inserisci_commento" */
{
$commento = new Commento();
$commento->setData(new \DateTime('now'));
$form = $this->createForm(new CommentoType($commento), $commento);
$request = $this->getRequest();
$form->handleRequest($request);
if ($form->isValid())
{
$em = $this->getDoctrine()->getManager();
try
{
$em->persist($commento);
$em->flush();
return $this->redirect('singlearticle');
} catch (\Exception $e)
{
$form->addError(new FormError('errore nel database'));
}
}
return $this->render('default/singlearticle.html.twig', array(
'commento' => $commento,
'form' => $form->createView()));
}
AND THE TEMPLATE
{% extends 'base.html.twig' %}
{% block body %}{% endblock %}
{% block maincontent %}
<div class="maincontent-title">{{article.titolo}} di {{article.autore}}</div>
<br>
<div class="tipologia">Categoria: {{article.categoria}}</div>
<div class="link" style="float:right;">Modifica</div>
<div class="link" style="float:right;padding-right: 25px;">Elimina</div>
<div class="rigaseparatrice"></div>
<br>
<article>
<p>
{%if article.image is not empty%}
<img class="imgarticolo" src="{{ asset('imgArticoli/' ~ article.id ~'/' ~ article.image)}}"/>
{%endif%}
<div class="titolo"></div>
<br>
<div class="testoarticolo">{{article.testo}}</div>
<br><br>
<br><br>
<div class="form-commento">
INSERISCI UN COMMENTO!
<form action="{{ path('inserisci_commento',{id:commento.id}) }}" method="post" {{ form_enctype(form) }} >
{{ form_errors(form) }}
{{ form_row(form.nome) }}
<br>
{{ form_row(form.testo) }}
<br>
{{ form_rest(form) }}
<input id="bottone" type="submit" value="INSERISCI" />
</form>
</div>
</p>
</article>
{% endblock %}
So, the problem is that when you insert a comment in the form, and I submit the form, I get an error, even if the data are now saved in the db.
Only one data (article_id) that is a Commento's parameter, is NULL, and I don't know why.
This is the error:
No route found for "GET /singlearticle" (from
"http://local/Sito/web/app_dev.php/singlearticle/1")
You need a refactor to the two actions from controller:
public function singlearticleAction($id)
{
//Codice di singlearticle
$art = $this->getDoctrine()->getEntityManager();
$article = $art->getRepository('AppBundle:Article')->find($id);
if (!$article){
throw $this->createNotFoundException('Non riesco a trovare questo articolo!');
}
//Fin qui
$form = $this->createForm(new CommentoType($article), new Commento());
return $this->render('default/singlearticle.html.twig', array(
'article' => $article,
'form' => $form->createView())
);
}
public function inserisci_commentoAction(Request $request, $articleId)
{
//Codice di singlearticle
$em = $this->getDoctrine()->getEntityManager();
$article = $em->getRepository('AppBundle:Article')->find($articleId);
if (!$article) {
throw $this->createNotFoundException('Non riesco a trovare questo articolo!');
}
$commento = new Commento();
$form = $this->createForm(new CommentoType($commento), $commento);
$form->handleRequest($request);
if ($form->isValid())
{
try
{
$commento->setData(new \DateTime('now'));
$commento->setArticle($article);
$em->persist($commento);
$em->flush();
// add a success message to session flashbag
} catch (\Exception $e)
{
// add a error message to session flashbag
}
}
return $this->redirect($this->generateUrl('singlearticle', array('id'=> $articleId)));
}
The route definition for inserisci_commento needs to be changed to:
inserisci_commento:
path: /singlearticle/{articleId}/inserisci_commento
defaults: {_controller: AppBundle:Default:inserisci_commento}
And in twig replace {{ path('inserisci_commento',{id:commento.id}) }} with {{ path('inserisci_commento',{articleId: article.id}) }}
Hope this helps
The problem is in your redirect statement. You need to pass in the article id.
return $this->redirect('singlearticle',array('id' => $article->getId());
whats definetly wrong is the mappedBy attribute in article class
/**
* #ORM\OneToMany(targetEntity="Commento", mappedBy="commento")
*/
protected $commento;
must be
/**
* #ORM\OneToMany(targetEntity="Commento", mappedBy="article")
*/
protected $commento;
and you have a typo in inversedBy attribute in comment class
/**
*#ORM\ManyToOne(targetEntity="Article",inversedBy="commenti")
* #ORM\JoinColumn(name="article_id",referencedColumnName="id")
*/
protected $article;
must be
/**
*#ORM\ManyToOne(targetEntity="Article",inversedBy="commento")
* #ORM\JoinColumn(name="article_id",referencedColumnName="id")
*/
protected $article;
I have 2 entities with one to many relationship project and prototype And I've been looking for a way to list the prototypes that belong to a project in the show action .
here is my project entity:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Projet
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="AppBundle\Entity\ProjetRepository")
*/
class Projet
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="nom", type="string", length=255)
*/
private $nom;
/**
* #var string
*
* #ORM\Column(name="description", type="string", length=255)
*/
private $description;
/**
* #var \DateTime
*
* #ORM\Column(name="dateCreation", type="date")
*/
private $dateCreation;
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Prototype", mappedBy="projet",cascade={"persist"} , orphanRemoval=true)
* #ORM\OrderBy({"id"="ASC"})
*/
protected $prototypes;
public function __construct()
{
$this->prototypes = new \Doctrine\Common\Collections\ArrayCollection();
$this->dateCreation = new \DateTime("now");
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set nom
*
* #param string $nom
* #return Projet
*/
public function setNom($nom)
{
$this->nom = $nom;
return $this;
}
/**
* Get nom
*
* #return string
*/
public function getNom()
{
return $this->nom;
}
public function __toString()
{
return $this->getNom();
}
/**
* Set description
*
* #param string $description
* #return Projet
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set dateCreation
*
* #param \DateTime $dateCreation
* #return Projet
*/
public function setDateCreation($dateCreation)
{
$this->dateCreation = $dateCreation;
return $this;
}
/**
* Get dateCreation
*
* #return \DateTime
*/
public function getDateCreation()
{
return $this->dateCreation;
}
public function setPrototypes($prototypes)
{
if (count($prototypes) > 0) {
foreach ($prototypes as $i) {
$this->addPrototypes($i);
}
}
return $this;
}
/**
* Add prototypes
*
* #param \AppBundle\Entity\Prototype $prototypes
* #return Projet
*/
public function addPrototypes(\AppBundle\Entity\Prototype $prototypes)
{
$this->prototypes[]= $prototypes;
return $this;
}
public function addPrototype(\AppBundle\Entity\Prototype $prototype)
{
$prototype->setProjet($this);
$this->prototypes->add($prototype);
}
/**
* Remove prototypes
*
* #param \AppBunble\Entity\Prototype $prototypes
*/
public function removePrototypes(\AppBundle\Entity\Prototype $prototypes)
{
$this->prototypes->removeElement($prototypes);
}
/**
* Get prototypes
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getPrototypes()
{
return $this->prototypes;
}
}
and here is my prototype entity
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Prototype
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="AppBundle\Entity\PrototypeRepository")
*/
class Prototype
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="nom", type="string", length=255)
*/
private $nom;
/**
* #var string
*
* #ORM\Column(name="description", type="string", length=255)
*/
private $description;
/**
* #var \DateTime
*
* #ORM\Column(name="dateCreation", type="date")
*/
private $dateCreation;
/**
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Projet", inversedBy="prototypes")
* #ORM\joinColumn(name="projet_id", referencedColumnName="id")
*/
private $projet;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Get nom
*
* #return string
*/
public function getNom()
{
return $this->nom;
}
public function __toString()
{
return $this->getNom();
}
/**
* Set nom
*
* #param string $nom
* #return Prototype
*/
public function setNom($nom)
{
$this->nom = $nom;
return $this;
}
/**
* Set description
*
* #param string $description
* #return Prototype
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set dateCreation
*
* #param \DateTime $dateCreation
* #return Prototype
*/
public function setDateCreation($dateCreation)
{
$this->dateCreation = $dateCreation;
return $this;
}
/**
* Get dateCreation
*
* #return \DateTime
*/
public function getDateCreation()
{
return $this->dateCreation;
}
/**
* Set projet
*
* #param \AppBundle\Entity\Projet $projet
* #return Prototype
*/
public function setProjet(\AppBundle\Entity\Projet $projet = null)
{
$this->projet = $projet;
return $this;
}
/**
* Get projet
*
* #return \AppBundle\Entity\Projet
*/
public function getProjet()
{
return $this->projet;
}
}
In my projetAdmin I can show in the ShowAction the prototypes :
here is projetAdmin :
<?php
namespace AppBundle\Admin;
use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;
use Sonata\AdminBundle\Route\RouteCollection;
class ProjetAdmin extends Admin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('nom', 'text', array('label' => 'Nom'))
->add('description','text',array('label'=>'Description'))
->add('dateCreation', 'date', array('label' => 'Date de création'))
;
}
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('nom')
->add('dateCreation')
;
}
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->add('nom')
->add('description')
->add('dateCreation')
->add('_action', 'actions', array(
'actions' => array(
'show' => array(),
'edit' => array(),
'delete' => array(),
)
)
)
;
}
protected function configureShowFields(ShowMapper $showMapper)
{
$showMapper
->add('prototypes')
;
}
}
I get the prototypes ( names )
But I would like to "list" the prototypes that belong to the project like the list view ( name , description of the prototype...)
How can I do that ?
One way is to define the template for your prototypes field in showMapper
protected function configureShowFields(ShowMapper $showMapper)
{
$showMapper ->add('prototypes',null, array('template' => 'NamespaceYourBundle::Admin/prototypes.html.twig'));
}
Create Admin folder in your bundle's resources folder and create prototypes.html.twig file ,extend your twig template with sonata's base_show_field.html.twig template and in {% block field %} define your own markup looping through all related prototypes
{% extends 'SonataAdminBundle:CRUD:base_show_field.html.twig' %}
{% block field %}
{% spaceless %}
{% if object.getPrototypes() is not empty %}
<table class="table table-bordered table-striped">
<thead>
<tr class="sonata-ba-list-field-header">
<th class="sonata-ba-list-field-header-text">Nom</th>
<th class="sonata-ba-list-field-header-text">Description</th>
...
...
...
</tr>
</thead>
<tbody>
{% for prototype in object.getPrototypes() %}
<tr>
<td class="sonata-ba-list-field sonata-ba-list-field-text">{{ prototype.getNom() }}</td>
<td class="sonata-ba-list-field sonata-ba-list-field-text">{{ prototype.getDescription() }}</td>
...
...
...
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% endspaceless %}
{% endblock %}
I found a way to resolve the problem but still I feel it's not the better way
I created a controller and overrided the showAction
<?php
namespace AppBundle\Controller;
use Sonata\AdminBundle\Route\RouteCollection;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Sonata\AdminBundle\Controller\CRUDController as Controller;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class CRUDController extends Controller
{
public function showAction($id = null)
{
return $this->redirect($this->generateUrl('admin_app_prototype_list', array(
'filter[projet__id][value]'=>$id
)));
}
}
Then I get a list of prototypes that belong to a project.
I am trying to set some translatable contents in Symfony2 with Gedmo Translatable but seems I am doing something wrong or missing something.
I included the line in the composer.json file:
"gedmo/doctrine-extensions": "2.3.*#dev"
And also, I added this lines in the config.yml file:
stof_doctrine_extensions:
orm:
alopatria:
timestampable: true
sluggable: true
translatable: true
The entity class is set like this:
<?php
namespace ...;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Translatable\Translatable;
/**
* ...\Entity
*
* #ORM\Table(name="content")
* #ORM\HasLifecycleCallbacks
* #ORM\Entity(repositoryClass="...\Entity\ContentRepository")
*/
class Content implements Translatable
{
/**
*
* #ORM\Column(name="id", type="bigint", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* #Gedmo\Translatable
* #ORM\Column(name="title", type="string", length=32, nullable=false)
*/
protected $title;
/**
* #Gedmo\Translatable
* #ORM\Column(name="text", type="text", nullable=false)
*/
protected $text;
/**
* #var datetime $created
*
* #Gedmo\Timestampable(on="create")
* #ORM\Column(type="datetime")
*/
private $created;
/**
* #var datetime $updated
*
* #Gedmo\Timestampable(on="update")
* #ORM\Column(type="datetime")
*/
private $updated;
/**
* #var datetime $contentChanged
*
* #ORM\Column(name="content_changed", type="datetime", nullable=true)
* #Gedmo\Timestampable(on="change", field={"title", "text"})
*/
private $contentChanged;
/**
* #Gedmo\Slug(fields={"title"})
* #ORM\Column(length=128, unique=true)
*/
private $slug;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set title
*
* #param string $title
* #return Content
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set text
*
* #param string $text
* #return Content
*/
public function setText($text)
{
$this->text = $text;
return $this;
}
/**
* Get text
*
* #return string
*/
public function getText()
{
return $this->text;
}
/**
* Set created
*
* #param \DateTime $created
* #return Content
*/
public function setCreated($created)
{
$this->created = $created;
return $this;
}
/**
* Get created
*
* #return \DateTime
*/
public function getCreated()
{
return $this->created;
}
/**
* Set updated
*
* #param \DateTime $updated
* #return Content
*/
public function setUpdated($updated)
{
$this->updated = $updated;
return $this;
}
/**
* Get updated
*
* #return \DateTime
*/
public function getUpdated()
{
return $this->updated;
}
/**
* Set contentChanged
*
* #param \DateTime $contentChanged
* #return Content
*/
public function setContentChanged($contentChanged)
{
$this->contentChanged = $contentChanged;
return $this;
}
/**
* Get contentChanged
*
* #return \DateTime
*/
public function getContentChanged()
{
return $this->contentChanged;
}
/**
* Set slug
*
* #param string $slug
* #return Content
*/
public function setSlug($slug)
{
$this->slug = $slug;
return $this;
}
/**
* Get slug
*
* #return string
*/
public function getSlug()
{
return $this->slug;
}
}
When I try to create a translatable content in my controller:
$content = new Content();
$content->setTitle('Content example');
$content->setText('Content example...');
$em = $this->getDoctrine()->getEntityManager();
$em->persist($content);
$em->flush();
$content->setTranslatableLocale('fr'); // change locale
$em->persist($content);
$em->flush();
This is the error:
The class 'Gedmo\Translatable\Entity\Translation' was not found in the chain configured namespaces ...\Entity, FOS\UserBundle\Model
Any help? Thanks!!!
You need to configure the translatable Entity to use as well. In config.yml:
orm:
auto_generate_proxy_classes: %kernel.debug%
mappings:
translatable:
type: annotation
is_bundle: false
prefix: Gedmo\Translatable\Entity
dir: "%kernel.root_dir%/../vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/Entity"
alias: GedmoTranslatable
I have that Entity TwitterPost.php
<?php
namespace FEB\TwitterBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Twitterpost
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="FEB\TwitterBundle\Entity\TwitterpostRepository")
* #ORM\HasLifecycleCallbacks()
*/
class Twitterpost
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="titulo", type="string", length=50)
* #Assert\NotNull(message="Debe escribir un titulo")
*/
private $titulo;
/**
* #var string
*
* #ORM\Column(name="tweet", type="string", length=145)
* #Assert\NotNull(message="Debe escribir un tweet")
*/
private $tweet;
/**
* Many-To-Many, Unidirectional
*
* #var ArrayCollection $tags
*
* #ORM\ManyToMany(targetEntity="\FEB\TagsBundle\Entity\Tag")
* #ORM\JoinTable(name="twitterpost_tags",
* joinColumns={#ORM\JoinColumn(name="twitterpost_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="tag", referencedColumnName="id")}
* )
*/
private $tags;
/**
* #var string
*
* #ORM\Column(name="photo", type="string", length=255, nullable=true)
*/
private $photo;
/**
* #var string
*
* #ORM\Column(name="idpost", type="string", length=100)
*/
private $idpost;
/**
* #var string
*
* #ORM\Column(name="autor", type="string", length=50)
*/
private $autor;
/**
* #var \DateTime
*
* #ORM\Column(name="created", type="datetime")
*/
private $created;
public function __construct()
{
$this->setCreated(new \DateTime());
$this->tags = new ArrayCollection();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set titulo
*
* #param string $titulo
* #return Twitterpost
*/
public function setTitulo($titulo)
{
$this->titulo = $titulo;
return $this;
}
/**
* Get titulo
*
* #return string
*/
public function getTitulo()
{
return $this->titulo;
}
/**
* Set tweet
*
* #param string $tweet
* #return Twitterpost
*/
public function setTweet($tweet)
{
$this->tweet = $tweet;
return $this;
}
/**
* Get tweet
*
* #return string
*/
public function getTweet()
{
return $this->tweet;
}
/**
* Set tags
*
* #param string $tags
* #return Twitterpost
*/
public function setTags($tags)
{
$this->tags = $tags;
return $this;
}
/**
* Get tags
*
* #return string
*/
public function getTags()
{
return $this->tags;
}
/**
* Set photo
*
* #param string $photo
* #return Twitterpost
*/
public function setPhoto($photo)
{
$this->photo = $photo;
return $this;
}
/**
* Get photo
*
* #return string
*/
public function getPhoto()
{
return $this->photo;
}
/**
* Set idpost
*
* #param string $idpost
* #return Twitterpost
*/
public function setIdPost($idpost)
{
$this->idpost = $idpost;
return $this;
}
/**
* Get idpost
*
* #return string
*/
public function getIdPost()
{
return $this->idpost;
}
/**
* Set autor
*
* #param string $autor
* #return Twitterpost
*/
public function setAutor($autor)
{
$this->autor = $autor;
return $this;
}
/**
* Get autor
*
* #return string
*/
public function getAutor()
{
return $this->autor;
}
/**
* Set created
*
* #param \DateTime $created
* #return Tag
*/
public function setCreated($created)
{
$this->created = $created;
return $this;
}
/**
* Get created
*
* #return \DateTime
*/
public function getCreated()
{
return $this->created;
}
}
And this one
/**
* Tag
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="FEB\TagsBundle\Entity\TagRepository")
* #ORM\HasLifecycleCallbacks()
*/
class Tag
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="tag", type="string", length=255)
*/
private $tag;
/**
* #var string
*
* #ORM\Column(name="autor", type="string", length=50)
*/
private $autor;
/**
* #var \DateTime
*
* #ORM\Column(name="created", type="datetime")
*/
private $created;
public function __construct()
{
$this->setCreated(new \DateTime());
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set tag
*
* #param string $tag
* #return Tag
*/
public function setTag($tag)
{
$this->tag = $tag;
return $this;
}
/**
* Get tag
*
* #return string
*/
public function getTag()
{
return $this->tag;
}
/**
* Set autor
*
* #param string $autor
* #return Tag
*/
public function setAutor($autor)
{
$this->autor = $autor;
return $this;
}
/**
* Get autor
*
* #return string
*/
public function getAutor()
{
return $this->autor;
}
/**
* Set created
*
* #param \DateTime $created
* #return Tag
*/
public function setCreated($created)
{
$this->created = $created;
return $this;
}
/**
* Get created
*
* #return \DateTime
*/
public function getCreated()
{
return $this->created;
}
}
It's a Manytomany relationship between TwitterPost and Tags. And in my form has a select field which is a Entity class Tag.
<?php
namespace FEB\TwitterBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class TwitterpostType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('titulo')
->add('tweet', 'textarea')
->add('photo', 'file', array('required' => false))
->add('tags', 'entity', array(
'class' => 'FEBTagsBundle:tag',
'property' => 'tag',
'empty_value' => 'Selecciona tags',
'multiple' => true));
}
public function getName()
{
return 'twitter_form';
}
}
When I submit the data form, in the "twitterpost" table the data is saved correctly and in the aux table "twitterpost_tags" too.
For example:
twitterpost_id tag_id
1-----------1
1-----------2
2-----------1
2-----------3
The tag table:
id---------tag
1----------tagA
2----------tagB
3----------tagC
When I want show all data of Twitterpost, what is the best approached to show the tag name and not the tag id?
Than you in advanced.
I'm not sure if I get you right. To show All tags in the twitterpost form you are already doing the right thing:
->add('tags', 'entity', array(
'class' => 'FEBTagsBundle:tag',
'property' => 'tag',
'empty_value' => 'Selecciona tags',
'multiple' => true
));
This will create a multiple select box where you can select from all the tags. From the docs:
property
type: string
This is the property that should be used for displaying the entities as text in the HTML element. If left blank, the entity object will be cast into a string and so must have a __toString() method.
If you don't want a multi-select but checkboxes or radiobuttons instead, checkout this part of the documentation.
In case you are asking on how to output the data when not inside the TwitterpostType, you can just treat them as objects in a Controller:
$repository = $this->getDoctrine()->getRepository('TwitterBundle:Twitterpost');
$post = $repository->findOne($id);
// to get all _tags_ of a post just call the getter:
$tags = $post->getTags();
The same goes for twig templates:
{# imagine you have all posts in a variable called 'posts' #}
{% for post in posts %}
<h1>{{ post.titulo }}</h1>
<div class="tags">
{% for tag in posts.tags %}
{{ tag.tag }}
{% endfor %}
</div>
{% endfor %}
Edit:
For a native SQL / DQL query you need a custom repository class. There you can store your own queries:
class TwitterpostRepository extends EntityRepository
{
public function findAllOrderedByName()
{
return $this->getEntityManager()
->createQuery(
'SELECT p FROM TwitterBundle:Twitterpost p ORDER BY p.name ASC'
)
->getResult();
}
}
Then you can use it like this in the controller:
$repository = $this->getDoctrine()->getRepository('TwitterBundle:Twitterpost');
$post = $repository->findAllOrderedByName();