Я использую Symfony 4 и простой администратор пакета для создания формы с несколькими коллекциями, вот мой код:
Produit.yaml
easy_admin:
entities:
Produit:
class: App\Entity\Produit
templates:
new: 'security/custom_produit.html.twig'
edit: 'security/custom_produit.html.twig'
form:
fields:
- nom
- {property: 'fiche_technique_file', label: 'Fiche technique', type: 'vich_file'}
- categorie
- { property: 'modele1', label: 'Modèle 1', type: 'collection', type_options: {entry_type: 'App\Form\Modele1Type', allow_add: true, allow_delete: true, by_reference: false} }
list:
fields: ['nom', {property: 'fiche_technique', label: 'Fiche technique'}, {property: 'categorie', label: 'Catégorie'},
{property: 'modele1', label: 'Modèle 1'}
Modele1Type. php
class Modele1Type extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('intro', CKEditorType::class)
->add('caract_tech', CKEditorType::class, [
'label' => 'Caractéristique technique'
])
->add('applications', TextareaType::class)
->add('info_comp_1', CKEditorType::class, [
'label' => 'Info complémentaire 1'
])
->add('info_comp_2', CKEditorType::class, [
'label' => 'Info complémentaire 2'
])
->add('info_comp_3', CKEditorType::class, [
'label' => 'Info complémentaire 3'
])
->add('galerie_photo', CollectionType::class, [
'entry_type' => MultipleImgModele1Type::class,
'prototype' => true,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'required' => false,
'label' => false,
])
->add('avantages', CollectionType::class, [
'entry_type' => AvantageType::class,
'prototype' => true,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'required' => false,
'label' => false,
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Modele1::class,
]);
}
}
Produit. php
/**
* @ORM\Entity(repositoryClass="App\Repository\ProduitRepository")
* @Vich\Uploadable()
*/
class Produit
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $nom;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $fiche_technique;
/**
* @Assert\File(
* maxSize = "5M",
* mimeTypes = {"application/pdf", "application/x-pdf"},
* mimeTypesMessage = "Veuillez envoyer un fichier PDF valide"
* )
* @Vich\UploadableField(mapping="produit_fiche_tech", fileNameProperty="fiche_technique")
*/
private $fiche_technique_file;
/**
* @ORM\Column(type="datetime", nullable=true)
*/
private $updated_at;
/**
* @ORM\ManyToOne(targetEntity="Categorie", inversedBy="produits")
*/
private $categorie;
/**
* @ORM\ManyToOne(targetEntity="Modele1", inversedBy="produits", cascade={"persist"})
* @ORM\JoinColumn(name="modele1_id", referencedColumnName="id", nullable=true)
*/
private $modele1;
public function __construct()
{
$this->updated_at = new \DateTime();
}
public function __toString()
{
$res = $this->nom;
if($this->modele1 != null) {
$res .= " - Modèle 1";
} else if($this->modele2 != null) {
$res .= " - Modèle 2";
} else if($this->modele3 != null) {
$res .= " - Modèle 3";
}
return $res;
}
public function getId(): ?int
{
return $this->id;
}
public function getNom(): ?string
{
return $this->nom;
}
public function setNom(string $nom): self
{
$this->nom = $nom;
return $this;
}
public function getFicheTechnique(): ?string
{
return $this->fiche_technique;
}
public function setFicheTechnique(?string $fiche_technique): self
{
$this->fiche_technique = $fiche_technique;
return $this;
}
public function getUpdatedAt(): ?\DateTimeInterface
{
return $this->updated_at;
}
public function setUpdatedAt(?\DateTimeInterface $updated_at): self
{
$this->updated_at = $updated_at;
return $this;
}
/**
* @return mixed
*/
public function getFicheTechniqueFile()
{
return $this->fiche_technique_file;
}
/**
* @param mixed $fiche_technique_file
* @throws \Exception
*/
public function setFicheTechniqueFile(?File $fiche_technique_file): void
{
$this->fiche_technique_file = $fiche_technique_file;
if($fiche_technique_file) {
$this->updated_at = new \DateTime();
}
}
/**
* @return mixed
*/
public function getCategorie(): ?Categorie
{
return $this->categorie;
}
/**
* @param mixed $categorie
*/
public function setCategorie(?Categorie $categorie): void
{
$this->categorie = $categorie;
}
/**
* @return mixed
*/
public function getModele1(): ?Modele1
{
return $this->modele1;
}
/**
* @param mixed $modele1
*/
public function setModele1($modele1): self
{
if(empty(array_values($modele1)[0])) {
$this->modele1 = null;
} else {
$this->modele1 = array_values($modele1)[0];
}
return $this;
}
}
Modele1. php
/**
* @ORM\Entity(repositoryClass="App\Repository\Modele1Repository")
*/
class Modele1
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="text")
*/
private $intro;
/**
* @ORM\Column(type="text")
*/
private $caract_tech;
/**
* @ORM\Column(type="text")
*/
private $applications;
/**
* @ORM\Column(type="text", nullable=true)
*/
private $info_comp_1;
/**
* @ORM\Column(type="text", nullable=true)
*/
private $info_comp_2;
/**
* @ORM\Column(type="text", nullable=true)
*/
private $info_comp_3;
/**
* @ORM\OneToMany(targetEntity="Produit", mappedBy="modele1", cascade={"persist"})
*/
private $produits;
/**
* @ORM\OneToMany(targetEntity="MultipleImgModele1", mappedBy="modele1", cascade={"persist", "remove"}, orphanRemoval=true)
*/
private $galerie_photo;
/**
* @ORM\OneToMany(targetEntity="Avantage", mappedBy="modele1")
*/
private $avantages;
public function __construct()
{
$this->produits = new ArrayCollection();
$this->galerie_photo = new ArrayCollection();
$this->avantages = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getIntro(): ?string
{
return $this->intro;
}
public function setIntro(string $intro): self
{
$this->intro = $intro;
return $this;
}
public function getCaractTech(): ?string
{
return $this->caract_tech;
}
public function setCaractTech(string $caract_tech): self
{
$this->caract_tech = $caract_tech;
return $this;
}
public function getApplications(): ?string
{
return $this->applications;
}
public function setApplications(string $applications): self
{
$this->applications = $applications;
return $this;
}
public function getInfoComp1(): ?string
{
return $this->info_comp_1;
}
public function setInfoComp1(?string $info_comp_1): self
{
$this->info_comp_1 = $info_comp_1;
return $this;
}
public function getInfoComp2(): ?string
{
return $this->info_comp_2;
}
public function setInfoComp2(?string $info_comp_2): self
{
$this->info_comp_2 = $info_comp_2;
return $this;
}
public function getInfoComp3(): ?string
{
return $this->info_comp_3;
}
public function setInfoComp3(?string $info_comp_3): self
{
$this->info_comp_3 = $info_comp_3;
return $this;
}
/**
* @return Collection|Produit
*/
public function getProduits(): Collection
{
return $this->produits;
}
public function addProduit(Produit $produits): self
{
if (!$this->produits->contains($produits)) {
$this->produits[] = $produits;
$produits->setModele1($this);
}
return $this;
}
public function removeProduit(Produit $produits): self
{
if ($this->produits->contains($produits)) {
$this->produits->removeElement($produits);
// set the owning side to null (unless already changed)
if ($produits->getModele1() === $this) {
$produits->setModele1(null);
}
}
return $this;
}
/**
* @return Collection|MultipleImgModele1[]
*/
public function getGaleriePhoto(): Collection
{
return $this->galerie_photo;
}
public function addGaleriePhoto(MultipleImgModele1 $galeriePhoto): self
{
if (!$this->galerie_photo->contains($galeriePhoto)) {
$this->galerie_photo[] = $galeriePhoto;
$galeriePhoto->setModele1($this);
}
return $this;
}
public function removeGaleriePhoto(MultipleImgModele1 $galeriePhoto): self
{
if ($this->galerie_photo->contains($galeriePhoto)) {
$this->galerie_photo->removeElement($galeriePhoto);
// set the owning side to null (unless already changed)
if ($galeriePhoto->getModele1() === $this) {
$galeriePhoto->setModele1(null);
}
}
return $this;
}
/**
* @return mixed
*/
public function getAvantages(): Collection
{
return $this->avantages;
}
public function addAvantage(Avantage $avantages): self
{
if (!$this->avantages->contains($avantages)) {
$this->avantages[] = $avantages;
$avantages->setModele1($this);
}
return $this;
}
public function removeAvantage(Avantage $avantages): self
{
if ($this->avantages->contains($avantages)) {
$this->avantages->removeElement($avantages);
// set the owning side to null (unless already changed)
if ($avantages->getModele1() === $this) {
$avantages->setModele1(null);
}
}
return $this;
}
}
custom_produit. html .twig
{% extends '@EasyAdmin/default/edit.html.twig' %}
{% block head_custom_stylesheets %}
{{ encore_entry_link_tags('app') }}
{% endblock %}
{% block main %}
{% block entity_form %}
{{ form_start(form) }}
<div class="container cont-modele-produit-admin mb-4">
<div class="accordion" id="accordionModeles">
<div class="row mb-4">
{% for model in form.modele1.vars.prototype %}
<div class="col-md-12 mt-3">
{% if model.vars.name == "galerie_photo" %}
<fieldset class="p-4">
<legend>Galerie Photos</legend>
{{ form_row(model) }}
</fieldset>
{% endif %}
{% if model.vars.name == "avantages" %}
<fieldset class="p-4">
<legend>Avantages</legend>
{{ form_row(model) }}
</fieldset>
{% endif %}
{{ form_label(model) }}
{{ form_widget(model) }}
</div>
{% endfor %}
{% do form.modele1.setRendered %}
</div>
</div>
</div>
{{ form_end(form) }}
{% endblock %}
{% endblock %}
{% block body_custom_javascript %}
{{ encore_entry_script_tags('app') }}
{% endblock %}
В функции setModele1 в объекте Produit мне пришлось сделать небольшое обновление получить данные сущности Modele1, потому что они дают мне такой массив:
Produit.php on line 180:
array:1 [▼
"__name__" => Modele1^ {#2564 ▼
-id: null
-intro: "<p>test</p>"
-caract_tech: "<p>test</p>"
-applications: "test"
-info_comp_1: null
-info_comp_2: null
-info_comp_3: null
-produits: ArrayCollection^ {#2577 ▶}
-galerie_photo: ArrayCollection^ {#2806 ▶}
-avantages: ArrayCollection^ {#2804 ▶}
}
]
он вернул мне ошибку, потому что должен получить объект Modele1 вместо массива, и теперь, когда я пытаюсь редактировать Produit, у Modele1 это выдает мне эту ошибку: Ожидаемый аргумент типа «массив или (\ Traversable and \ ArrayAccess)», «Proxies__CG __ \ App \ Entity \ Modele1» задан
Так почему же Мне нужно дать массив вместо сущности Modele1, чтобы получить все данные и поместить их в форму для редактирования?
Извините за мой плохой английский sh I h Опе, вы все поймете, что я хотел сделать ^^
Заранее благодарю за помощь!