Greetings to all. I was assigned to upgrade the existing site, which is written in Symfony 2. Now there is a list of news, you need to add a gallery to them. I created the "news_gallery" table:

  • id integer NOT NULL [pk]
  • title character varying (255)
  • image character varying (255) NOT NULL
  • id_news integer [fk]

Created a NewsGallery class:

namespace AppBundle\Entity; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\HttpFoundation\File\File; use Symfony\Component\Validator\Constraints as Assert; use Vich\UploaderBundle\Mapping\Annotation as Vich; /** * Image * * @ORM\Table(name="news_gallery") * @ORM\Entity(repositoryClass="AppBundle\Repository\NewsGallerysRepository") * @Vich\Uploadable */ class NewsGallerys { /** * @var int * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @var string * * @ORM\Column(name="title", type="string", length=255, nullable=true) */ private $title; /** * @var string * * @ORM\Column(name="image", type="string", length=1024) */ private $image; /** * @Assert\File( * maxSize="2m", * mimeTypes={"image/png", "image/jpeg"} * ) * @Vich\UploadableField(mapping="newsgallery", fileNameProperty="image") * @var File */ private $imageFile; public function setImageFile(File $image = null) { $this->imageFile = $image; } public function getImageFile() { return $this->imageFile; } /** * @ORM\ManyToOne(targetEntity="News", inversedBy="news_gallerys") * @ORM\JoinColumn(name="id_news", referencedColumnName="id") */ public $news; /** * Set news * * @param \AppBundle\Entity\News $news * * @return news_gallerys */ public function setIdNews(\AppBundle\Entity\News $news) { $this->news = $news; return $this; } /** * Get news * * @return \AppBundle\Entity\News */ public function getIdNews() { return $this->news; } /** * Get id * * @return integer */ public function getId() { return $this->id; } /** * Set title * * @param string $title * @return Image */ public function setTitle($title) { $this->title = $title; return $this; } /** * Get title * * @return string */ public function getTitle() { return $this->title; } /** * Set image * * @param string $image * @return Image */ public function setImage($image) { $this->image = $image; return $this; } /** * Get image * * @return string */ public function getImage() { return $this->image; } } 

In the News class added a link:

 namespace AppBundle\Entity; use Doctrine\ORM\Mapping as ORM; use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\ArrayCollection; use Symfony\Component\HttpFoundation\File\File; use Vich\UploaderBundle\Mapping\Annotation as Vich; /** * News * * @ORM\Table(name="news") * @ORM\Entity(repositoryClass="AppBundle\Repository\NewsRepository") * @ORM\HasLifecycleCallbacks() * @Vich\Uploadable */ class News { /** * @ORM\OneToMany(targetEntity="NewsGallerys", mappedBy="news") */ private $news_gallerys; /** * Add news_gallerys * * @param \AppBundle\Entity\NewsGallerys $news_gallerys * * @return News */ public function addNewsGallery(\AppBundle\Entity\NewsGallerys $news_gallerys) { $this->news_gallerys[] = $news_gallerys; return $this; } /** * Remove news_gallerys * * @param \AppBundle\Entity\NewsGallerys $news_gallerys */ public function removeNewsGallery(\AppBundle\Entity\NewsGallerys $news_gallerys) { $this->news_gallerys->removeElement($news_gallerys); } /** * Get news_gallerys * * @return \Doctrine\Common\Collections\Collection */ public function getNewsGallery() { return $this->news_gallerys; } .... } 

In the public part of the site in the template this gallery is displayed. But I have no idea how to generate this field in the form of adding news through the admin area. I reread a bunch of documentation and a bunch of forums, but I can't find anything.

Here is part of the config.yml file for News and the gallery itself:

 News: label: app.menu.news class: AppBundle\Entity\News list: fields: - name - shortDescription show: fields: - name - shortDescription - fullDescription form: fields: - { property: 'created' } - name - shortDescription - fullDescription NewsGallerys: label: app.menu.news_gallery class: AppBundle\Entity\NewsGallerys list: fields: - title - { property: 'image', type: 'image', base_path: %app.path.newsgallery% } show: fields: - title - { property: 'image', type: 'image', base_path: %app.path.newsgallery% } form: fields: - title - { property: 'imageFile', type: 'vich_image' } 

How to add the "news_gallerys" property in News so that you can upload infinitely many photos?

Thank you for attention.

    2 answers 2

    The solution was found thanks to this guy . He routinely used the type of "collection"

    Here's what I get in the end: the News.php file

     namespace AppBundle\Entity; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\HttpFoundation\File\File; use Vich\UploaderBundle\Mapping\Annotation as Vich; /** * News * * @ORM\Table(name="news") * @ORM\Entity(repositoryClass="AppBundle\Repository\NewsRepository") * @ORM\HasLifecycleCallbacks() * @Vich\Uploadable */ class News { /** * @var datetime $created * * @ORM\Column(type="datetime") */ protected $created; /** * @return datetime */ public function getCreated() { return $this->created; } public function setCreated($newdate) { $this->created = $newdate; return $this; } /** * @var datetime $updated * * @ORM\Column(type="datetime", nullable = true) */ protected $updated; /** * Gets triggered only on insert * @ORM\PrePersist */ public function onPrePersist() { $this->created = new \DateTime("now"); } /** * Gets triggered every time on update * @ORM\PreUpdate */ public function onPreUpdate() { $this->updated = new \DateTime("now"); } /** * @var int * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @var string * * @ORM\Column(name="name", type="string", length=255) */ private $name; /** * @var string * * @ORM\Column(name="shortDescription", type="string", length=1024) */ private $shortDescription; /** * @var string * * @ORM\Column(name="fullDescription", type="text") */ private $fullDescription; /** * Get id * * @return integer */ public function getId() { return $this->id; } /** * Set name * * @param string $name * @return News */ public function setName($name) { $this->name = $name; return $this; } /** * Get name * * @return string */ public function getName() { return $this->name; } /** * Set shortDescription * * @param string $shortDescription * @return News */ public function setShortDescription($shortDescription) { $this->shortDescription = $shortDescription; return $this; } /** * Get shortDescription * * @return string */ public function getShortDescription() { return $this->shortDescription; } /** * Set fullDescription * * @param string $fullDescription * @return News */ public function setFullDescription($fullDescription) { $this->fullDescription = $fullDescription; return $this; } /** * Get fullDescription * * @return string */ public function getFullDescription() { return $this->fullDescription; } /** * @var string * * @ORM\Column(name="image", type="string", length=1024) */ private $image; /** * Set image * * @param string $image * @return Image */ public function setImage($image) { $this->image = $image; return $this; } /** * Get image * * @return string */ public function getImage() { return $this->image; } /** * @Vich\UploadableField(mapping="newsgallery", fileNameProperty="image") * @var File */ private $imageFile; public function setImageFile(File $image = null) { $this->imageFile = $image; } public function getImageFile() { return $this->imageFile; } /** * @ORM\OneToMany(targetEntity="NewsGallerys", mappedBy="news") */ private $news_gallerys; public function __construct() { $this->news_gallerys = new ArrayCollection(); } public function __toString() { return (string)$this->name; } /** * Add news_gallerys * * @param \AppBundle\Entity\NewsGallerys $news_gallerys * * @return News */ public function addNewsGallerys(\AppBundle\Entity\NewsGallerys $news_gallerys) { $this->news_gallerys[] = $news_gallerys; return $this; } /** * Remove news_gallerys * * @param \AppBundle\Entity\NewsGallerys $news_gallerys */ public function removeNewsGallerys(\AppBundle\Entity\NewsGallerys $news_gallerys) { $this->news_gallerys->removeElement($news_gallerys); } /** * Get news_gallerys * * @return NewsGallerys[]|ArrayCollection */ public function getNewsGallerys() { return $this->news_gallerys; } } 

    File NewsGallerys.php

     namespace AppBundle\Entity; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\HttpFoundation\File\File; use Symfony\Component\Validator\Constraints as Assert; use Vich\UploaderBundle\Mapping\Annotation as Vich; /** * Image * * @ORM\Table(name="news_gallery") * @ORM\Entity(repositoryClass="AppBundle\Repository\NewsGallerysRepository") * @Vich\Uploadable */ class NewsGallerys { /** * @var int * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @var string * * @ORM\Column(name="title", type="string", length=255, nullable=true) */ private $name; /** * @var string * * @ORM\Column(name="image", type="string", length=1024) */ private $image; /** * @Assert\File( * maxSize="2m", * mimeTypes={"image/png", "image/jpeg"} * ) * @Vich\UploadableField(mapping="newsgallery", fileNameProperty="image") * @var File */ private $imageFile; /** * Get id * * @return integer */ public function getId() { return $this->id; } /** * Set title * * @param string $title * @return NewsGallerys */ public function setName($name) { $this->title = $name; return $this; } /** * Get title * * @return string */ public function getName() { return $this->name; } /** * Set image * * @param File|null $image * @return NewsGallerys */ public function setImageFile(File $image = null) { $this->imageFile = $image; return $this; } /** * @return File */ public function getImageFile() { return $this->imageFile; } /** * @param string $image * @return NewsGallerys */ public function setImage($image) { $this->image = $image; return $this; } /** * Get image * * @return string */ public function getImage() { return $this->image; } /** * @ORM\ManyToOne(targetEntity="News",cascade={"persist", "remove"},inversedBy="news_gallerys") * @ORM\JoinColumn(name="id_news",referencedColumnName="id",nullable=true) */ public $news; public function __toString(){ return (string) $this->name; } } 

    in the config.yml for the entity News has prescribed the following fields:

     News: label: app.menu.news class: AppBundle\Entity\News list: fields: - name - shortDescription show: fields: - name - shortDescription - fullDescription - { property: 'image', type: 'image', base_path: %app.path.newsgallery% } form: fields: - { property: 'created' } - name - shortDescription - fullDescription - { property: 'imageFile', type: 'vich_image' } - { property: 'news_gallerys', type: 'collection', type_options: { entry_type: 'AppBundle\Form\ImageType' } } 

    Next, create a file ImageType.php:

     namespace AppBundle\Form; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; use Vich\UploaderBundle\Form\Type\VichFileType; class ImageType extends AbstractType { /** * @param FormBuilderInterface $builder * @param array $options */ public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('name') ->add('imageFile', VichFileType::class) ; } /** * @param OptionsResolver $resolver */ public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( 'data_class' => 'AppBundle\Entity\NewsGallerys' )); } } 

    As a result, I receive multiple additions of files with a picture type, if they have already been added to the database, it is displayed correctly, but I can’t add a new one or delete it. Displays error:

    request.CRITICAL: Uncaught PHP Exception Doctrine \ ORM \ ORMInvalidArgumentException: "To understand this subject: Either explicitly: #ManineToOne (.., cascade = {"persist"}). "

    If someone tells you how to solve it, I will be grateful.

    • If possible, publish the solution found completely I am sure it will help many of your colleagues in the future. - Nicolas Chabanovsky
    • While I can not put out a complete ready-made solution, the question was solved only with the display of fields in the admin panel. While deciding the issue with the error when saving the news: request.CRITICAL: Uncaught PHP Exception Doctrine \ ORM \ ORMInvalidArgumentException: "If you’re not : #Edit.ManyToOne (.., cascade = {"persist"}). " - E.Elena

    Hello!

    Here is a link - your case is described there: http://symfony.com/doc/current/form/form_collections.html#allowing-new-tags-with-the-prototype

    In short:

    • you need to add the option allow_add = true in the news_gallerys field, and
      necessary - allow_delete = true

    • then display the prototype in the template for adding images:

      data-prototype = "{{form_widget (form.tags.vars.prototype) | e ('html_attr')}}"

    • and fasten js to add form elements

    • Greetings, thanks for the reply. I am not a very experienced symfony programmer, so I don’t understand how to use this one. I work with the form in the admin panel, namely EasyAdmin. Those. I need to add and delete photos for the news gallery, cascade when adding or editing "news". - E.Elena
    • Look, you have in konfagah described form for News, in which you added the field news_gallerys. It is necessary to add 2 parameters to type_options - allow_add: true, allow_delete: true. Thus, Symfony will understand that it is possible through the News form to add and delete Entity Objects NewsGallerys. Further, in the form template, for a div (or table, depends on how you display the news gallery) add the data-prototype attribute. This attribute will store the html prototype of ImageType (this is like a form without data, only html). Next you need to fasten js code to add / remove list items - Victor