How to join two table in symfony 5? - php

I'm a beginner in Symfony and here is my problem.
More precisely, I have two table in my DB. The first one is called 'post' and the other is called 'article'. The post table is the parent entity of article which mean that the article entity inherite from the post entity. What I would like to is to join this two table to get data from my database.
However, after reading the doctrine and symfony docs about mapping inheritance, I still cannot solve my problem.
Could you help me to solve this problem please ?
N.B : here is my code
Article class :
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Articles
*
* #ORM\Table(name="articles")
* #ORM\Entity(repositoryClass="App\Repository\ArticlesRepository")
*/
class Articles
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var int
*
* #ORM\Column(name="post", type="integer", nullable=false )
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $post;
/**
* #ORM\Column(type="string", length=255)
*/
private $themes;
/**
* Articles constructor.
* #param int $post
*/
public static $themeAvailable = [
0 => "Environnement",
1 => "Economie",
2 => "Science et technologie",
3 => "Loisir",
4 => "Culture générale",
5 => "Art",
6 => "Sport"
];
public function getId(): ?int
{
return $this->id;
}
public function getPost(): ?int
{
return $this->post;
}
public function getThemes(): ?string
{
return $this->themes;
}
public function setThemes(string $themes): self
{
$this->themes = $themes;
return $this;
}
public function setPost(int $post)
{
$this->post = $post;
}
}
Post class :
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Posts
*
* #ORM\Table(name="posts")
* #ORM\Entity(repositoryClass="App\Repository\PostsRepository")
*/
class Posts
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var int
*
* #ORM\Column(name="author", type="integer", nullable=false)
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $author;
/**
* #var string
* #Assert\NotBlank()
* #ORM\Column(name="title", type="string", length=255, nullable=false)
*/
private $title;
/**
* #var string
* #Assert\NotBlank()
* #ORM\Column(name="content", type="text", length=65535, nullable=false)
*/
private $content;
/**
* #var string
* #Assert\File(
* maxSize = "20M",
* maxSizeMessage = "La taille du fichier trop importante. Minimum autorisé : 20 Mo.",
* mimeTypes = {"image/svg","image/png", "image/jpg", "image/jpeg", "image/gif" },
* mimeTypesMessage = "Format du fichier incorrecte. Formats autorisés : svg, png, jpg, jpeg, gif.",
* disallowEmptyMessage = "Veuillez importer une image supérieur à 0 Mo."
* )
* #ORM\Column(name="image", type="blob", length=65535, nullable=false)
*/
private $image;
/**
* #var \DateTime
*
* #ORM\Column(name="creation_date", type="datetime", nullable=false, options={"default"="CURRENT_TIMESTAMP"})
*/
private $creationDate;
/**
* Posts constructor.
*/
public function __construct()
{
$this->creationDate = new \DateTime();
}
public function getId(): ?int
{
return $this->id;
}
public function getAuthor(): ?int
{
return $this->author;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
public function getContent(): ?string
{
return $this->content;
}
public function setContent(string $content): self
{
$this->content = $content;
return $this;
}
public function getImage(): string
{
return $this->image;
}
public function setImage($image): self
{
$this->image = $image;
return $this;
}
public function getCreationDate(): ?\DateTimeInterface
{
return $this->creationDate;
}
public function setCreationDate(\DateTimeInterface $creationDate): self
{
$this->creationDate = $creationDate;
return $this;
}
public function setAuthor(int $author)
{
$this->author = $author;
}
}
My Repository :
public function findAllArticle()
{
return $this->createQueryBuilder('a')
->join('a.post',
'p')
->addSelect('p')
->getQuery()
->getResult();
}
And here is my controller :
<?php
namespace App\Controller;
use App\Entity\Articles;
use App\Entity\Posts;
use App\Form\PostsArticleType;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class PostArticleController extends \Symfony\Bundle\FrameworkBundle\Controller\AbstractController
{
/**
* #var EntityManagerInterface
*/
private $em;
/**
* ArticleController constructor.
* #param EntityManagerInterface $em
*/
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
/**
* #Route("/post/create", name="index")
* #return Response
*/
public function index(): Response
{
return $this->render('post/index.html.twig');
}
/**
* #Route("/post/article/show", name="showArticle")
* #return Response
*/
public function show(): Response
{
$articles = $this->getDoctrine()
->getManager()
->getRepository(Articles::class)
->findAllArticle();
return $this->render('post/showArticle.html.twig', array('article' => $articles));
}
/**
* #Route("/post/article/new", name="newArticle")
* #param Request $request
* #return Response
*/
public function new(Request $request): Response
{
$post = new Posts();
$article = new Articles();
$post->setAuthor(1);
$form = $this->createForm(PostsArticleType::class, $post);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid())
{
$this->em->persist($post);
$this->em->flush();
$article->setPost($post->getId());
$themes = $form->get('themes')->getData();
$article->setThemes(implode(',', $themes));
$this->em->persist($article);
$this->em->flush();
return $this->redirectToRoute('home.html.twig');
}
return $this->render('post/CreateArticle.html.twig', ['form' => $form->createView()]);
}
}

As you have two tables posts and articles, you can use "JOINED" inheritance:
The Posts class should look like:
/*...*/
/**
* Posts
*
* #ORM\Table(name="posts")
* #ORM\Entity(repositoryClass="App\Repository\PostsRepository")
*
* #ORM\InheritanceType("JOINED")
* #ORM\DiscriminatorColumn(name="discr", type="string")
* #ORM\DiscriminatorMap({"posts" = "Posts", "articles" = "Articles"})
*/
class Posts
{
/*...*/
}
For Articles class:
/*...*/
/**
* Articles
*
* #ORM\Table(name="articles")
* #ORM\Entity(repositoryClass="App\Repository\ArticlesRepository")
*/
class Articles extends Posts
{
/*...*/
}
For the posts table, you will have the Posts class properties, and a column called 'discr' configured in DiscriminatorColumn parameter (see Posts class).
For the articles table, you will have the Articles class properties, and 'posts_id' column, which is a foreign key (it references 'id' column of 'posts' table).
There are some helpful links :
Doctrine : Class Table Inheritance
About Doctrine inheritance - Section: Class Table Inheritance

Related

SQLSTATE[42S22]: Column not found: 1054 Unknown column in 'field list' while trying to sort entities

I am trying to implement sorting in my Symfony 6 project.
Here is the entity I am trying to sort :
<?php
namespace App\Entity;
use App\Entity\Workflow\Status;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use App\Entity\Plant;
use App\Entity\DetailedCause;
/**
* #ORM\Entity(repositoryClass=\App\Repository\RequestRepository::class)
*/
class Request
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string")
*/
private $requesterName;
/**
* #ORM\Column(type="string")
*/
private $requesterService;
/**
* #ORM\Column(type="string")
*/
private $requesterMatricule;
/**
* #ORM\Column(type="integer")
*/
private $priority;
/**
* #ORM\Column(type="integer")
*/
private $type;
/**
* #ORM\Column(type="boolean")
*/
private $flagSupp;
/**
* #ORM\Column(type="integer", nullable=true)
*/
private $estimatedLoad;
/**
* #ORM\Column(type="text")
*/
private $reason;
/**
* #ORM\Column(type="datetime", nullable=false)
*/
private $date;
/**
* #ORM\ManyToOne(targetEntity=Workflow\Status::class)
* #ORM\JoinColumn(nullable=false)
*/
private Status $state;
/**
* #ORM\Column(type="string", length=50, nullable=true)
*/
private $product;
/**
* #ORM\Column(type="string", length=50, nullable=true)
*/
private $program;
/**
* #ORM\ManyToOne(targetEntity=DetailedCause::class)
* #ORM\JoinColumn(nullable=false)
*/
private DetailedCause $detailedCause;
/**
* #ORM\ManyToOne(targetEntity=Cause::class)
*/
private $cause;
/**
* #ORM\ManyToOne(targetEntity=Plant::class)
* #ORM\JoinColumn(nullable=false)
*/
private Plant $impactedPlant;
/**
* #ORM\OneToMany(targetEntity=Action::class, mappedBy="request")
*/
private $actions;
/**
* #ORM\ManyToOne(targetEntity=Plant::class)
* #ORM\JoinColumn(nullable=false)
*/
private Plant $requesterPlant;
public function __construct()
{
$this->actions = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getRequesterPlant(): ?Plant
{
return $this->requesterPlant;
}
public function setRequesterPlant(?Plant $requesterPlant): self
{
$this->requesterPlant = $requesterPlant;
return $this;
}
//the rest of getters and setters
}
and the repository :
<?php
namespace App\Repository;
use App\Entity\Request;
use App\Entity\RequestFilter;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\Tools\Pagination\Paginator;
use Doctrine\Persistence\ManagerRegistry;
use App\Entity\Plant;
/**
* #method Request|null find($id, $lockMode = null, $lockVersion = null)
* #method Request|null findOneBy(array $criteria, array $orderBy = null)
* #method Request[] findAll()
* #method Request[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
* #method Paginator getRequestPaginator(int $offset = 0, string $order = 'id')
*/
class RequestRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Request::class);
}
/**
* #var int $offset
* #param RequestFilter
* #return Paginator Returns a paginator of requests using filters
*/
public function getRequestPaginator($offset = 0, RequestFilter $filter = null)
{
if ($filter == null) {
$filter = new RequestFilter();
}
#adds filter parameters to the query
$query = $this->createQueryBuilder('r');
if ($filter->getStates() != null){
$query
->andWhere('r.state IN (:states)')
->setParameter('states', $filter->getStates());//;
}
#adds the rest of the params
$query = $query
//this orderBy clause is triggering the error
->orderBy('r.' . $filter->getOrder(), $filter->getOrderDirection())
->setFirstResult($offset)
->setMaxResults($filter->getRequestsPerPage())
->getQuery();
return new Paginator($query);
}
}
this works fine for most attributes. I can sort by date, requester name, etc.
But when I try to sort by requesterPlant, which is a doctrine Entity, I get the following error :
("An exception occurred while executing a query: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'r0_.requester_plant_id' in 'field list'").
This column does exist in the database just like other columns. I do not understand why doctrine is stuck on this. Migrations are up to date, I've cleared cache, and I've been stuck on this problem for days.
I would really appreciate if anyone had a clue about what is happening there.
As additional info, here is my Plant entity :
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass=\App\Repository\PlantRepository::class)
*/
class Plant
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
* #ORM\OneToMany(targetEntity="App\Entity\Request", mappedBy="requesterPlant")
*/
private int $id;
/**
* #ORM\Column(type="string", length=255)
*/
private string $designation;
/**
* #ORM\Column(type="string", length=50)
*/
private string $plantString;
/**
* #ORM\Column(type="string", length=50)
*/
private string $company;
public function getId(): ?int
{
return $this->id;
}
public function setID(int $id): self
{
$this->id = $id;
return $this;
}
public function getDesignation(): ?string
{
return $this->designation;
}
public function setDesignation(string $designation): self
{
$this->designation = $designation;
return $this;
}
public function getPlantString(): ?string
{
return $this->plantString;
}
public function setPLantString(string $plantString): self
{
$this->plantString = $plantString;
return $this;
}
public function getCompany(): ?string
{
return $this->company;
}
public function setCompany(string $company): self
{
$this->company = $company;
return $this;
}
}

Relation One to Many return empty object

I have a Evaluation entity which has one Product and Product which can have several Evaluations. I'm trying to fetch one Product and to get the list of Evaluations associated with my entity
Produit.php
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use phpDocumentor\Reflection\Types\This;
/**
* Produit
*
* #ORM\Table(name="produit", indexes={#ORM\Index(name="fk_idcatedel", columns={"idCategorie"})})
* #ORM\Entity
*/
class Produit
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string|null
*
* #ORM\Column(name="libelle", type="string", length=20, nullable=true)
*/
private $libelle;
/**
* #var float|null
*
* #ORM\Column(name="prix", type="float", precision=10, scale=0, nullable=true)
*/
private $prix;
/**
* #var string|null
*
* #ORM\Column(name="description", type="string", length=50, nullable=true)
*/
private $description;
/**
* #var int
*
* #ORM\Column(name="qt", type="integer", nullable=false)
*/
private $qt;
/**
* #var string|null
*
* #ORM\Column(name="img", type="string", length=255, nullable=true)
*/
private $img;
/**
* #var \Categorie
*
* #ORM\ManyToOne(targetEntity="Categorie")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="idCategorie", referencedColumnName="id")
* })
*/
private $idcategorie;
/**
* #ORM\OneToMany(targetEntity="Evaluation", mappedBy="idProduit")
*/
private $rates;
public function __construct()
{
$this->rates = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getLibelle(): ?string
{
return $this->libelle;
}
public function setLibelle(?string $libelle): self
{
$this->libelle = $libelle;
return $this;
}
public function getPrix(): ?float
{
return $this->prix;
}
public function setPrix(?float $prix): self
{
$this->prix = $prix;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(?string $description): self
{
$this->description = $description;
return $this;
}
public function getQt(): ?int
{
return $this->qt;
}
public function setQt(int $qt): self
{
$this->qt = $qt;
return $this;
}
public function getImg(): ?string
{
return $this->img;
}
public function setImg(?string $img): self
{
$this->img = $img;
return $this;
}
public function getIdcategorie(): ?Categorie
{
return $this->idcategorie;
}
public function setIdcategorie(?Categorie $idcategorie): self
{
$this->idcategorie = $idcategorie;
return $this;
}
/**
* #return Collection|Evaluation[]
*/
public function getRates(): Collection
{
return $this->rates;
}
}
Evaluation.php
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Evaluation
*
* #ORM\Table(name="evaluation", indexes={#ORM\Index(name="fk_idprodevaldel", columns={"id_produit"}), #ORM\Index(name="fk_iduser", columns={"id_user"})})
* #ORM\Entity
*/
class Evaluation
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var int
*
* #ORM\Column(name="note", type="integer", nullable=false)
*/
private $note;
/**
* #var \Produit
*
* #ORM\ManyToOne(targetEntity="Produit", inversedBy="rates")
* #ORM\JoinColumn(name="id_produit", referencedColumnName="id")
*/
private $idProduit;
/**
* #var \Compte
*
* #ORM\ManyToOne(targetEntity="Compte")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="id_user", referencedColumnName="email")
* })
*/
private $idUser;
public function getId(): ?int
{
return $this->id;
}
public function getNote(): ?int
{
return $this->note;
}
public function setNote(int $note): self
{
$this->note = $note;
return $this;
}
public function getIdProduit(): ?Produit
{
return $this->idProduit;
}
public function setIdProduit(?Produit $idProduit): self
{
$this->idProduit = $idProduit;
return $this;
}
public function getIdUser(): ?Compte
{
return $this->idUser;
}
public function setIdUser(?Compte $idUser): self
{
$this->idUser = $idUser;
return $this;
}
}
The database
In my controller I succeed to get informations from the products but rates are empty
$produits = $this->getDoctrine()
->getRepository(Produit::class)
->find(1);
dump($produits);
$rates = $produits->getRates();
dump($rates); // #collection: ArrayCollection is empty
The Output :
The collection is not yet initialized due to lazy loading, and rightfully so. If you don't access at least to an element in the collection, it's pointless to load the whole collection because doctrine can safely assume you'll "discard" it. As soon as you access an element (either by looping onto collection or getting a specific element), the collection will be initialized and you have all items.
Another way is to use an EAGER fetch that will load the whole collection in the hydration phase. I would not reccomend it however, unless you're sure that everytime you load a Produit, you need this collection "ready". Even in the latter case, I would handle the collection "manually" as I recommend not to lose control on it (let's pretend you have A LOT of element inside it).
Read more about proxies and association, here

Symfony4: Expected argument of type "Categorie", "instance of App\Entity\Categorie" given at property path "categorie"

I am having an issue with the EntityType class in Symfony 4 where I cannot find a way to make the form row return a string instead of an entity (Categorie). This is what I basically have as part of the form builder: ProduitType
$builder
->add('nom')
->add('prix')
->add('imgproduit')
->add('categorie', EntityType::class, [
'class' => Categorie::class,
'choice_label' => 'titre'
])
;
My aim is to have this field return the title(titre) for the Categorie selected, not the entire entity (so, the exact same value as the 'choice_label'). I've already tried adding __toString to my Entity Produit but its the same problem
this is my Entity Produit in which I am using titre from Categorie as an attribut named categorie
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Produit
*
* #ORM\Table(name="produit", uniqueConstraints={#ORM\UniqueConstraint(name="nom", columns={"nom"})}, indexes={#ORM\Index(name="fk_p_ct", columns={"categorie"})})
* #ORM\Entity
*/
class Produit
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="nom", type="string", length=20, nullable=false)
*/
private $nom;
/**
* #var float
*
* #ORM\Column(name="prix", type="float", precision=10, scale=0, nullable=false)
*/
private $prix;
/**
* #var string
*
* #ORM\Column(name="imgproduit", type="string", length=200, nullable=false)
*/
private $imgproduit;
/**
* #var \Categorie
*
* #ORM\ManyToOne(targetEntity=Categorie::class, inversedBy="categories")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="categorie", referencedColumnName="titre")
* })
*/
private $categorie;
/**
* #return int
*/
public function getId(): int
{
return $this->id;
}
/**
* #param int $id
*/
public function setId(int $id): void
{
$this->id = $id;
}
/**
* #return string
*/
public function getNom(): ?string
{
return $this->nom;
}
/**
* #param string $nom
*/
public function setNom(string $nom): void
{
$this->nom = $nom;
}
/**
* #return float
*/
public function getPrix(): ?float
{
return $this->prix;
}
/**
* #param float $prix
*/
public function setPrix(float $prix): void
{
$this->prix = $prix;
}
/**
* #return string
*/
public function getImgproduit(): ?string
{
return $this->imgproduit;
}
/**
* #param string $imgproduit
*/
public function setImgproduit(string $imgproduit): void
{
$this->imgproduit = $imgproduit;
}
/**
* #return \Categorie
*/
public function getCategorie(): ?\Categorie
{
return $this->categorie;
}
/**
* #param \Categorie $categorie
*/
public function setCategorie(\Categorie $categorie): self
{
$this->categorie = $categorie;
return $this;
}
public function __toString()
{
return $this->nom;
}
}
How would I be able to achieve my goal?
Read the error carefully, expected "Category", got "App\Entity\Category"
It should expect "App\Entity\Category" the problem is with your setter:
/**
* #param \Categorie $categorie
*/
public function setCategorie(\Categorie $categorie): self
{
$this->categorie = $categorie;
return $this;
}
You are declaring the parameter type to be \Categorie from the global namespace. What you need is Categorie from the current namespace (App\Entity) or \App\Entity\Categorie.
The solution is to change ALL of the occurrences of \Categorie to Categorie or \App\Entity\Categorie within the file but, especially in your setter method to resolve this particular error:
/**
* #param Categorie $categorie
*/
public function setCategorie(Categorie $categorie): self
{
$this->categorie = $categorie;
return $this;
}
OR
/**
* #param \App\Entity\Categorie $categorie
*/
public function setCategorie(\App\Entity\Categorie $categorie): self
{
$this->categorie = $categorie;
return $this;
}

Multiple file upload with VlabsMediaBundle in Symfony2

i'm trying to make a multiple upload file on an entity with the vlabsmediaBundle.
So i have an advert who can have many images but each can be linked with only one advert.
I followed the tutorial(tuto) of the bundle but get an error.
Here:
Entity Image.php
namespace MDB\PlatformBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Vlabs\MediaBundle\Entity\BaseFile as VlabsFile;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Image
*
* #ORM\Table()
* #ORM\Entity
*/
class Image extends VlabsFile {
/**
* #var string
*
* #ORM\Column(name="url", type="string", length=255)
*/
private $url;
/**
* #var string
*
* #ORM\Column(name="alt", type="string", length=255)
*/
private $alt;
/**
* #ORM\ManyToOne(targetEntity="MDB\AnnonceBundle\Entity\Annonce", inversedBy="images")
* #ORM\JoinColumn(nullable=true)
*/
private $annonce;
/**
* Get id
*
* #return integer
*/
public function getId() {
return $this->id;
}
/**
* Set url
*
* #param string $url
* #return Image
*/
public function setUrl($url) {
$this->url = $url;
return $this;
}
/**
* Get url
*
* #return string
*/
public function getUrl() {
return $this->url;
}
/**
* Set alt
*
* #param string $alt
* #return Image
*/
public function setAlt($alt) {
$this->alt = $alt;
return $this;
}
/**
* Get alt
*
* #return string
*/
public function getAlt() {
return $this->alt;
}
public function getAnnonce() {
return $this->annonce;
}
public function setAnnonce($annonce) {
$this->annonce = $annonce;
}
/**
* #var string $path
*
* #ORM\Column(name="path", type="string", length=255)
* #Assert\Image()
*/
private $path;
/**
* Set path
*
* #param string $path
* #return Image
*/
public function setPath($path) {
$this->path = $path;
return $this;
}
/**
/**
* Get path
*
* #return string
*/
public function getPath() {
return $this->path;
}
}
Annonce.php (advert enity)
<?php
namespace MDB\AnnonceBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
use Vlabs\MediaBundle\Annotation\Vlabs;
/**
* Annonce
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="MDB\AnnonceBundle\Entity\AnnonceRepository")
*/
class Annonce {
public function __construct() {
$this->date = new \Datetime();
$this->categories = new ArrayCollection();
$this->images = new ArrayCollection();
}
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="titre", type="string", length=255)
*/
private $titre;
/**
* #var string
*
* #ORM\Column(name="description", type="string", length=255)
*/
private $description;
/**
* #ORM\Column(name="date", type="date")
*/
private $date;
/**
* #var float
*
* #ORM\Column(name="prix", type="float")
*/
private $prix;
/**
* #ORM\ManyToOne(targetEntity="MDB\AdresseBundle\Entity\Ville", inversedBy="annonces")
*/
private $ville;
/**
* #ORM\ManyToMany(targetEntity="MDB\AnnonceBundle\Entity\Category", cascade={"persist"})
*/
private $categories;
/**
* #ORM\ManyToMany(targetEntity="MDB\UserBundle\Entity\User")
*
*/
private $wishlist;
/**
* #var boolean
*
* #ORM\Column(name="telAppear", type="boolean")
*/
private $telAppear;
/**
* #ORM\ManyToOne(targetEntity="MDB\UserBundle\Entity\User", inversedBy="annonces")
* #ORM\JoinColumn(nullable=false)
*/
private $user;
/**
* #var VlabsFile
* #ORM\OneToMany(targetEntity="MDB\PlatformBundle\Entity\Image", mappedBy="annonce")
* #Vlabs\Media(identifier="image_entity", upload_dir="files/images")
* #Assert\Valid()
*/
private $images;
/**
* Get id
*
* #return integer
*/
public function getId() {
return $this->id;
}
/**
* Set titre
*
* #param string $titre
* #return Annonce
*/
public function setTitre($titre) {
$this->titre = $titre;
return $this;
}
/**
* Get titre
*
* #return string
*/
public function getTitre() {
return $this->titre;
}
/**
* Set description
*
* #param string $description
* #return Annonce
*/
public function setDescription($description) {
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription() {
return $this->description;
}
/**
* Set prix
*
* #param float $prix
* #return Annonce
*/
public function setPrix($prix) {
$this->prix = $prix;
return $this;
}
/**
* Get prix
*
* #return float
*/
public function getPrix() {
return $this->prix;
}
public function addCategory(Category $category) {
// Ici, on utilise l'ArrayCollection vraiment comme un tableau
$this->categories[] = $category;
return $this;
}
public function removeCategory(Category $category) {
$this->categories->removeElement($category);
}
public function getCategories() {
return $this->categories;
}
public function getDate() {
return $this->date;
}
public function setDate($date) {
$this->date = $date;
}
public function getWishlist() {
return $this->wishlist;
}
public function setWishlist($wishlist) {
$this->wishlist = $wishlist;
}
public function getVille() {
return $this->ville;
}
public function setVille($ville) {
$this->ville = $ville;
}
public function getTelAppear() {
return $this->telAppear;
}
public function setTelAppear($telAppear) {
$this->telAppear = $telAppear;
}
public function getUser() {
return $this->user;
}
public function setUser($user) {
$this->user = $user;
}
public function addImage(Image $image) {
$this->images[] = $image;
$image->setUser($this);
return $this;
}
public function removeImage(Image $image) {
$this->images->removeElement($image);
}
public function getImages() {
return $this->images;
}
}
config.yml
vlabs_media:
image_cache:
cache_dir: files/c
mapping:
image_entity:
class: MDB\PlatformBundle\Entity\Image
AnnonceSellType.php
<?php
namespace MDB\AnnonceBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use MDB\PlatformBundle\Form\ImageType;
class AnnonceSellType extends AbstractType {
private $arrayListCat;
public function __construct( $arrayListCat)
{
$this->arrayListCat = $arrayListCat;
}
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->remove('wishlist')
->remove('date')
->remove('images')
->add('titre')
->add('description', 'textarea')
->add('prix')
->add('categories', 'choice', array(
'choices' => $this->arrayListCat,
'multiple' => true,
'mapped'=>false,
))
//->add('images', 'collection', array('type' => new ImageType()))
->add('image', 'vlabs_file', array(
'required' => false
))
;
}
/**
* #return string
*/
public function getName() {
return 'mdb_annoncebundle_annonce_sell';
}
public function getParent() {
return new AnnonceType();
}
}
And i have the following error : Catchable Fatal Error: Argument 1 passed to Vlabs\MediaBundle\EventListener\BaseFileListener::preSetData() must be an instance of Symfony\Component\Form\Event\DataEvent, instance of Symfony\Component\Form\FormEvent given in C:\wamp\www\Mdb\vendor\vlabs\media-bundle\Vlabs\MediaBundle\EventListener\BaseFileListener.php line 59
i tried to change this line :
->add('image', 'vlabs_file', array(
'required' => false
))
with :
->add('images', 'collection', array('type' => 'vlabs_file'))
but i just have the image label who appear in this case
if someone have an idea ?
I was a little bit investigating about your problem and Vlabs Media Bundle seems to be unmaintained. There is form listener on PRE_SET_DATA event (Vlabs\MediaBundle\EventListener\BaseFileListener::preSetData()) that is not compatible with new version of Symfony (it expects DataEvent as parametr instead FormEvent). They fixed it but after 1.1.1 release (you can compare dates from links). If really wanna give a try, change composer.json and run composer update. I can't guarantee there will not be another possible issues.
composer.json
"vlabs/media-bundle": "dev-master"
Library update
composer update vlabs/media-bundle

symfony2 entity field type error

I haven't found any solid example on how to do this.
I have my entity Shield, which can have more than 1 ShieldTypes. What I want to do is, create a form that creates a new Shield with different Shieldtypes.
This is my code, I honestly don't know where is my error:
Error is:
Entities passed to the choice field must be managed
500 Internal Server Error - FormException
Armory\SearchBundle\Entity\Shield.php
namespace Armory\SearchBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Armory\SearchBundle\Entity\Shield
*
* #ORM\Table(name="shield")
* #ORM\Entity
*/
class Shield
{
/**
* #var integer $id
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string $name
* #ORM\Column(name="name", type="string", length=45, nullable=false)
*/
private $name;
/**
* #var integer $defense
* #ORM\Column(name="defense", type="integer", nullable=false)
*/
private $defense;
/**
* #var boolean $active
* #ORM\Column(name="active", type="boolean", nullable=false)
*/
private $active;
/**
* #ORM\ManyToMany(targetEntity="ShieldTypes")
* #ORM\JoinTable(name="i_orbs_type",
* joinColumns={#ORM\JoinColumn(name="id_orb", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="id_type", referencedColumnName="id")}
* )
* #var ArrayCollection $types
*/
protected $types;
public function __construct(){
$this->types = new \Doctrine\Common\Collections\ArrayCollection();
}
public function getTypes(){
return $this->types;
}
public function getId()
{
return $this->id;
}
public function setName($name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
public function setDefense($defense)
{
$this->defense = $defense;
}
public function getDefense()
{
return $this->defense;
}
public function setActive($active)
{
$this->active = $active;
}
public function getActive()
{
return (bool)$this->active;
}
}
Armory\SearchBundle\Form\ShieldType.php:
namespace Armory\SearchBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
class ShieldType extends AbstractType{
public function buildForm(FormBuilder $builder, array $options){
$builder->add('name','text');
$builder->add('defense','integer');
$builder->add('active','checkbox');
$builder->add('types','entity',
array(
'class'=>'Armory\SearchBundle\Entity\ShieldTypes',
'query_builder'=> function($repository){
return $repository->createQueryBuilder('t')->orderBy('t.id', 'ASC');
},
'property'=>'name', )
);
}
public function getName(){
return 'shield';
}
public function getDefaultOptions(array $options){
return array('data_class'=>'Armory\\SearchBundle\\Entity\\Shield');
}
}
Armory\SearchBundle\Entity\ShieldTypes.php
namespace Armory\SearchBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* SOA\CRMBundle\Entity\ShieldTypes
*
* #ORM\Table(name="orbs_type")
* #ORM\Entity
*/
class ShieldTypes
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* #var string $name
*
* #ORM\Column(name="name", type="string", length=45, nullable=false)
*/
private $name;
/**
* #var string $title
*
* #ORM\Column(name="title", type="string", length=45, nullable=false)
*/
private $title;
public function getId()
{
return $this->id;
}
public function setName($name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
public function setTitle($title)
{
$this->title = $title;
}
public function getTitle()
{
return $this->title;
}
}
It can be a little confusing but:
Shield entity (database)
ShieldTypes entity (database)
ShieldType form (abstracttype)
Thank you...
So the problem was that I didn't create a repository. I created it (see code at the end) and I still got 'Entities passed to the choice field must be managed' error.
Then I set mutiple to true in:
$builder->add('types','entity',
array(
'class'=>'Armory\SearchBundle\Entity\ShieldTypes',
'query_builder'=> function(\Armory\SearchBundle\Entity\Repository\ShieldTypesRepository $repository){
return $repository->createQueryBuilder('s')->orderBy('s.id', 'ASC');},
'property'=>'title',
'multiple'=>true
)
);
I hope someone finds this useful, cause if I had had this, it would been easier.
Code for my repository:
namespace Armory\SearchBundle\Entity\Repository;
use Doctrine\ORM\EntityRepository;
class ShieldTypesRepository extends EntityRepository
{
public function getAll()
{
return $this->_em->createQuery('SELECT s FROM Armory\SearchBundle\Entity\ShieldTypes s')
->getResult();
}
}

Categories