gpt4 book ai didi

symfony - "Multiple Upload"与 Symfony 3 上的 VichUploaderBundle

转载 作者:行者123 更新时间:2023-12-02 17:08:45 29 4
gpt4 key购买 nike

我尝试使用 bundle VichUploader 允许多次上传。在这个项目中,我有一个类(class)剧院,它拥有一个主图像,但也有一些次要图像(图像集合)。实际上每一个副图都是一个资源。所以一个剧院有一个多资源,一个资源连接到一个剧院。

但是当我尝试创建时,我可以访问我的表单,但是当我尝试保存时出现错误:

Expected argument of type "AppBundle\Entity\Resources", "AppBundle\Entity\Theatre" given 

这是我的类(class)剧院,只有多次上传的详细信息:

namespace AppBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Vich\UploaderBundle\Mapping\Annotation as Vich;

/**
* Theatre
*
* @ORM\Table(name="theatre")
* @ORM\Entity
* @Vich\Uploadable
*/
class Theatre
{

/**
* @var ArrayCollection
* @ORM\OneToMany(targetEntity="Resources", mappedBy="theatre", cascade={"persist", "remove"}, orphanRemoval=true)
*/
private $images;

// ..

/**
* Constructor
*/
public function __construct()
{
$this->images = new \Doctrine\Common\Collections\ArrayCollection();
}

// MultiUpload
/**
* @return ArrayCollection
*/
public function getImages()
{
return $this->images;
}

/**
* @param ArrayCollection $pictures
*/
public function setImages($pictures)
{
$this->images = $pictures;
}

public function getAttachImages()
{
return null;
}

/**
* @param array $files
*
* @return array
*/
public function setAttachImages(array $files=array())
{
if (!$files) return [];
foreach ($files as $file) {
if (!$file) return [];
$this->attachImages($file);
}
return [];
}

/**
* @param UploadedFile|null $file
*/
public function attachImages(UploadedFile $file=null)
{
if (!$file) {
return;
}
$picture = new Resources();
$picture->setImage($file);
$this->addImage($picture);
}



/**
* Add image.
*
* @param \AppBundle\Entity\Resources $image
*
*
*/
public function addImage(\AppBundle\Entity\Resources $image)
{
$image->setTheatre($this);
//$this->images->add($image);
$this->images[] = $image;

//return $this;
}

/**
* Remove image.
*
* @param \AppBundle\Entity\Resources $image
*
*
*/
public function removeImage(\AppBundle\Entity\Resources $image)
{
$image->setTheatre(null);
$this->images->removeElement($image);
// return $this->images->removeElement($image);
}

然后是我的类资源:

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
use Vich\UploaderBundle\Mapping\Annotation as Vich;

/**
* Resources
*
* @ORM\Table(name="resources")
* @ORM\Entity
* @Vich\Uploadable
*/
class Resources
{

/**
* @var Theatre
* @ORM\ManyToOne(targetEntity="Theatre", inversedBy="images")
*/
private $theatre;

/**
* @Vich\UploadableField(mapping="uploads_image", fileNameProperty="url")
* @Assert\File(
* mimeTypes = {"image/png", "image/jpeg", "image/jpg"},
* mimeTypesMessage = "Please upload a valid valid IMAGE"
* )
*
*
* @var File $image
*/
protected $image;

/**
* @ORM\Column(type="string", length=255, name="url")
*
* @var array $url
*/
protected $url;


/**
*
* @param File|\Symfony\Component\HttpFoundation\File\UploadedFile $image
*
* @return Theatre
*/
public function setImage(File $image = null)
{
$this->image = $image;
}

public function getImage()
{
return $this->image;
}

// ..

/**
* Set theatre.
*
* @param \AppBundle\Entity\Theatre $theatre
*
* @return Resources
*/
public function setTheatre(\AppBundle\Entity\Theatre $theatre)
{
$this->theatre = $theatre;

return $this;
}

/**
* Get theatre.
*
* @return \AppBundle\Entity\Theatre
*/
public function getTheatre()
{
return $this->theatre;
}

/**
* Set url.
*
* @param string $url
*
* @return Resources
*/
public function setUrl($url)
{
$this->url = $url;

return $this;
}

/**
* Get url.
*
* @return array
*/
public function getUrl()
{
return $this->url;
}

然后我添加到构建器中:

namespace AppBundle\Form\Collection;

use AppBundle\Entity\Theatre;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Vich\UploaderBundle\Form\Type\VichFileType;


class TheatreImages extends AbstractType{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('attachImages', FileType::class, ['multiple'=>true, 'required'=>false])
;


}

/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Theatre::class,
));
}

/**
* @return string
*/
public function getName()
{
return 'app_theatreImages';
}
}

我使用 bundle easyAdminBundle 添加我的配置:

easy_admin:
entities:
Theatre:
class: AppBundle\Entity\Theatre
list:
title: 'Liste des théâtres'
fields:
- 'Name'
- 'adress'
- 'Metro station'
- { property: 'Main image', type: 'image', template: 'theatreFile.html.twig', base_path: '%app.path.theatre_images%' }

new:
title: 'Création théâtre'
fields:
- { type: 'section', label: 'Information du théâtre' }
- {property: 'name', label: 'Nom'}
- {property: 'number_of_seats', type: 'integer', label: 'Nombre de sièges'}
- {property: 'about', label: 'description'}
- { property: 'imageFile', type: 'vich_file', label: 'image', type_options: { required: false}}
- {property: 'images', type: 'collection', type_options: {entry_type: 'AppBundle\Form\Collection\TheatreImages', by_reference: false}}
- { type: 'section', label: 'Localisation du théâtre' }
- {property: 'adress', label: 'adresse'}
- {property: 'metro_station', label: 'Station de métro'}
- {property: 'location_coordinates', label: 'Coordonnées'}
edit:
title: "Édition théâtre"
fields:
- { type: 'section', label: 'Information du théâtre' }
- {property: 'name', label: 'Nom'}
- {property: 'number_of_seats', type: 'integer', label: 'Nombre de sièges'}
- {property: 'about', label: 'description'}
- { property: 'imageFile', type: 'vich_file', label: 'image', type_options: { required: false}}
- {property: 'images', type: 'collection', type_options: {entry_type: 'AppBundle\Form\Collection\TheatreImages', by_reference: false}}
- { type: 'section', label: 'Localisation du théâtre' }
- {property: 'adress', label: 'adresse'}
- {property: 'metro_station', label: 'Station de métro'}
- {property: 'location_coordinates', label: 'Coordonnées'}

提前致谢。

最佳答案

我已经为一个非常有用的包 [VichUploader] 创建了一个解决方案,它缺少多次上传的功能,并且它适用于我在 [Symfony] 5.2 上创建的每个 Symfony 版本。它在 OneToMany 关系上并且工作正常。所以我在我的自定义表单中使用了 CollectionType 和 [VichFileType] 并在我的 Controller 中使用了一些小技巧,这里是代码并查看所有项目,你可以在我的 GitHub 中找到它[链接] https://github.com/malek-laatiri

Admission.php

class Admission
{
/**
* @ORM\OneToMany(targetEntity=Diplome::class, mappedBy="admission")
*/
private $diplomes;
/**
* @return Collection|Diplome[]
*/
public function getDiplomes(): Collection
{
return $this->diplomes;
}

public function addDiplome(Diplome $diplome): self
{
if (!$this->diplomes->contains($diplome)) {
$this->diplomes[] = $diplome;
$diplome->setAdmission($this);
}

return $this;
}

public function removeDiplome(Diplome $diplome): self
{
if ($this->diplomes->removeElement($diplome)) {
// set the owning side to null (unless already changed)
if ($diplome->getAdmission() === $this) {
$diplome->setAdmission(null);
}
}

return $this;
}
}

文凭.php

<?php

namespace App\Entity;

use App\Repository\DiplomeRepository;
use Doctrine\ORM\Mapping as ORM;
use Vich\UploaderBundle\Mapping\Annotation as Vich;


/**
* @ORM\Entity(repositoryClass=DiplomeRepository::class)
* @Vich\Uploadable
*/
class Diplome
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;

/**
* @ORM\ManyToOne(targetEntity=Admission::class, inversedBy="diplomes",cascade={"persist","remove"})
*/
private $admission;

/**
* @ORM\Column(type="string", length=255)
*/
private $name;

/**
* @Vich\UploadableField(mapping="product_image", fileNameProperty="name")
* @var File
*/
private $file;

public function getId(): ?int
{
return $this->id;
}

public function getAdmission(): ?Admission
{
return $this->admission;
}

public function setAdmission(?Admission $admission): self
{
$this->admission = $admission;

return $this;
}

public function getName(): ?string
{
return $this->name;
}

public function setName(string $name): self
{
$this->name = $name;

return $this;
}

public function getFile()
{
return $this->file;
}

public function setFile( $file)
{
$this->file = $file;

return $this;
}
}

AdmissionType.php

<?php

namespace App\Form;

use App\Entity\Admission;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Vich\UploaderBundle\Form\Type\VichFileType;

class Admission1Type extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('diplomes', CollectionType::class, [
'entry_type' => DiplomeType::class,
'allow_add' => true,
'allow_delete' => true,
'required' => false,
'label'=>false,
'by_reference' => false,
'disabled' => false,
]);
}

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Admission::class,
]);
}
}

DiplomeType.php

<?php

namespace App\Form;

use App\Entity\Diplome;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Vich\UploaderBundle\Form\Type\VichFileType;

class DiplomeType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('file',VichFileType::class)
;
}

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Diplome::class,
"allow_extra_fields" => true,
]);
}
}

_form.html.twig

<ul id="diplomes-fields-list"
data-prototype="{{ form_widget(form.diplomes.vars.prototype)|e }}"
data-widget-tags="{{ '<li></li>'|e }}"
data-widget-counter="{{ form.diplomes|length }}">
{% for emailField in form.diplomes %}
<li>
{{ form_errors(emailField) }}
{{ form_widget(emailField) }}
</li>
{% endfor %}
</ul>
<button type="button"
class="add-another-collection"
data-list-selector="#diplomes-fields-list">Add another email
</button>

script.js

jQuery(document).ready(function () {
jQuery('.add-another-collection').click(function (e) {
var list = $("#diplomes-fields-list");
var counter = list.data('widget-counter') | list.children().length;
var newWidget = list.attr('data-prototype');
newWidget = newWidget.replace(/__name__/g, counter);
counter++;
list.data('widget-counter', counter);

var newElem = jQuery(list.attr('data-widget-tags')).html(newWidget);
newElem.appendTo(list);
newElem.append('<a href="#" class="remove-tag" style="color: darkred">remove</a>');
$('.remove-tag').click(function(e) {
e.preventDefault();

$(this).parent().remove();

});
});
});

Controller.php

$admission = new Admission();
$form = $this->createForm(Admission1Type::class, $admission);
$form->handleRequest($request);
$entityManager = $this->getDoctrine()->getManager();
if ($form->isSubmitted() && $form->isValid()) {
foreach ($form->getData()->getNotes() as $dip){
$entityManager->persist($dip);
$admission->addNote($dip);
}
$entityManager->persist($admission);
$entityManager->flush();

关于symfony - "Multiple Upload"与 Symfony 3 上的 VichUploaderBundle,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50383209/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com