MrF*_*rid 2 file-upload symfony vichuploaderbundle symfony-3.4
我尝试允许使用捆绑包 VichUploader 进行多次上传。在该项目中,我有一个类剧院,它拥有一个主图像,但也有一些辅助图像(图像集合)。实际上,每个辅助图像都是一个资源。\n因此,一个剧院有一个多个资源,一个资源连接到一个剧院。
\n\n但是当我尝试创建时,我可以访问我的表单,但当我尝试保存时出现错误:
\n\nExpected argument of type "AppBundle\\Entity\\Resources", "AppBundle\\Entity\\Theatre" given \nRun Code Online (Sandbox Code Playgroud)\n\n这是我的班级剧院,仅包含多次上传的详细信息:
\n\nnamespace AppBundle\\Entity;\n\nuse Doctrine\\Common\\Collections\\ArrayCollection;\nuse Doctrine\\ORM\\Mapping as ORM;\nuse Symfony\\Component\\HttpFoundation\\File\\File;\nuse Symfony\\Component\\HttpFoundation\\File\\UploadedFile;\nuse Symfony\\Component\\Validator\\Constraints as Assert;\nuse Symfony\\Component\\Validator\\Context\\ExecutionContextInterface;\nuse Vich\\UploaderBundle\\Mapping\\Annotation as Vich;\n\n/**\n* Theatre\n*\n* @ORM\\Table(name="theatre")\n* @ORM\\Entity\n* @Vich\\Uploadable\n*/\nclass Theatre\n{\n\n/**\n * @var ArrayCollection\n * @ORM\\OneToMany(targetEntity="Resources", mappedBy="theatre", cascade={"persist", "remove"}, orphanRemoval=true)\n */\nprivate $images;\n\n// ..\n\n/**\n * Constructor\n */\npublic function __construct()\n{\n $this->images = new \\Doctrine\\Common\\Collections\\ArrayCollection();\n}\n\n// MultiUpload\n/**\n * @return ArrayCollection\n */\npublic function getImages()\n{\n return $this->images;\n}\n\n/**\n * @param ArrayCollection $pictures\n */\npublic function setImages($pictures)\n{\n $this->images = $pictures;\n}\n\npublic function getAttachImages()\n{\n return null;\n}\n\n/**\n * @param array $files\n *\n * @return array\n */\npublic function setAttachImages(array $files=array())\n{\n if (!$files) return [];\n foreach ($files as $file) {\n if (!$file) return [];\n $this->attachImages($file);\n }\n return [];\n}\n\n/**\n * @param UploadedFile|null $file\n */\npublic function attachImages(UploadedFile $file=null)\n{\n if (!$file) {\n return;\n }\n $picture = new Resources();\n $picture->setImage($file);\n $this->addImage($picture);\n}\n\n\n\n/**\n * Add image.\n *\n * @param \\AppBundle\\Entity\\Resources $image\n *\n *\n */\npublic function addImage(\\AppBundle\\Entity\\Resources $image)\n{\n $image->setTheatre($this);\n //$this->images->add($image);\n $this->images[] = $image;\n\n //return $this;\n}\n\n/**\n * Remove image.\n *\n * @param \\AppBundle\\Entity\\Resources $image\n *\n *\n */\npublic function removeImage(\\AppBundle\\Entity\\Resources $image)\n{\n $image->setTheatre(null);\n $this->images->removeElement($image);\n // return $this->images->removeElement($image);\n}\nRun Code Online (Sandbox Code Playgroud)\n\n然后我的班级资源:
\n\nnamespace AppBundle\\Entity;\n\nuse Doctrine\\ORM\\Mapping as ORM;\nuse Symfony\\Component\\HttpFoundation\\File\\File;\nuse Symfony\\Component\\HttpFoundation\\File\\UploadedFile;\nuse Symfony\\Component\\Validator\\Constraints as Assert;\nuse Symfony\\Component\\Validator\\Context\\ExecutionContextInterface;\nuse Vich\\UploaderBundle\\Mapping\\Annotation as Vich;\n\n/**\n* Resources\n*\n* @ORM\\Table(name="resources")\n* @ORM\\Entity\n* @Vich\\Uploadable\n*/\nclass Resources\n{\n\n /**\n * @var Theatre\n * @ORM\\ManyToOne(targetEntity="Theatre", inversedBy="images")\n */\nprivate $theatre;\n\n/**\n * @Vich\\UploadableField(mapping="uploads_image", fileNameProperty="url")\n * @Assert\\File(\n * mimeTypes = {"image/png", "image/jpeg", "image/jpg"},\n * mimeTypesMessage = "Please upload a valid valid IMAGE"\n * )\n *\n *\n * @var File $image\n */\nprotected $image;\n\n/**\n * @ORM\\Column(type="string", length=255, name="url")\n *\n * @var array $url\n */\nprotected $url;\n\n\n/**\n *\n * @param File|\\Symfony\\Component\\HttpFoundation\\File\\UploadedFile $image\n *\n * @return Theatre\n */\npublic function setImage(File $image = null)\n{\n $this->image = $image;\n}\n\npublic function getImage()\n{\n return $this->image;\n}\n\n// ..\n\n /**\n * Set theatre.\n *\n * @param \\AppBundle\\Entity\\Theatre $theatre\n *\n * @return Resources\n */\npublic function setTheatre(\\AppBundle\\Entity\\Theatre $theatre)\n{\n $this->theatre = $theatre;\n\n return $this;\n}\n\n/**\n * Get theatre.\n *\n * @return \\AppBundle\\Entity\\Theatre\n */\npublic function getTheatre()\n{\n return $this->theatre;\n}\n\n/**\n * Set url.\n *\n * @param string $url\n *\n * @return Resources\n */\npublic function setUrl($url)\n{\n $this->url = $url;\n\n return $this;\n}\n\n/**\n * Get url.\n *\n * @return array\n */\npublic function getUrl()\n{\n return $this->url;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n然后我添加到构建器:
\n\nnamespace AppBundle\\Form\\Collection;\n\nuse AppBundle\\Entity\\Theatre;\nuse Symfony\\Component\\Form\\AbstractType;\nuse Symfony\\Component\\Form\\Extension\\Core\\Type\\FileType;\nuse Symfony\\Component\\Form\\FormBuilderInterface;\nuse Symfony\\Component\\OptionsResolver\\OptionsResolver;\nuse Symfony\\Bridge\\Doctrine\\Form\\Type\\EntityType;\nuse Vich\\UploaderBundle\\Form\\Type\\VichFileType;\n\n\nclass TheatreImages extends AbstractType{\n/**\n * @param FormBuilderInterface $builder\n * @param array $options\n */\npublic function buildForm(FormBuilderInterface $builder, array $options)\n{\n $builder\n ->add(\'attachImages\', FileType::class, [\'multiple\'=>true, \'required\'=>false])\n ;\n\n\n}\n\n/**\n * @param OptionsResolver $resolver\n */\npublic function configureOptions(OptionsResolver $resolver)\n{\n $resolver->setDefaults(array(\n \'data_class\' => Theatre::class,\n ));\n}\n\n/**\n * @return string\n */\npublic function getName()\n{\n return \'app_theatreImages\';\n}\n}\nRun Code Online (Sandbox Code Playgroud)\n\n我使用捆绑包 easyAdminBundle 添加我的配置:
\n\neasy_admin:\n entities:\n Theatre:\n class: AppBundle\\Entity\\Theatre\n list:\n title: \'Liste des th\xc3\xa9\xc3\xa2tres\'\n fields:\n - \'Name\'\n - \'adress\'\n - \'Metro station\'\n - { property: \'Main image\', type: \'image\', template: \'theatreFile.html.twig\', base_path: \'%app.path.theatre_images%\' }\n\n new:\n title: \'Cr\xc3\xa9ation th\xc3\xa9\xc3\xa2tre\'\n fields:\n - { type: \'section\', label: \'Information du th\xc3\xa9\xc3\xa2tre\' }\n - {property: \'name\', label: \'Nom\'}\n - {property: \'number_of_seats\', type: \'integer\', label: \'Nombre de si\xc3\xa8ges\'}\n - {property: \'about\', label: \'description\'}\n - { property: \'imageFile\', type: \'vich_file\', label: \'image\', type_options: { required: false}}\n - {property: \'images\', type: \'collection\', type_options: {entry_type: \'AppBundle\\Form\\Collection\\TheatreImages\', by_reference: false}}\n - { type: \'section\', label: \'Localisation du th\xc3\xa9\xc3\xa2tre\' }\n - {property: \'adress\', label: \'adresse\'}\n - {property: \'metro_station\', label: \'Station de m\xc3\xa9tro\'}\n - {property: \'location_coordinates\', label: \'Coordonn\xc3\xa9es\'}\n edit:\n title: "\xc3\x89dition th\xc3\xa9\xc3\xa2tre"\n fields:\n - { type: \'section\', label: \'Information du th\xc3\xa9\xc3\xa2tre\' }\n - {property: \'name\', label: \'Nom\'}\n - {property: \'number_of_seats\', type: \'integer\', label: \'Nombre de si\xc3\xa8ges\'}\n - {property: \'about\', label: \'description\'}\n - { property: \'imageFile\', type: \'vich_file\', label: \'image\', type_options: { required: false}}\n - {property: \'images\', type: \'collection\', type_options: {entry_type: \'AppBundle\\Form\\Collection\\TheatreImages\', by_reference: false}}\n - { type: \'section\', label: \'Localisation du th\xc3\xa9\xc3\xa2tre\' }\n - {property: \'adress\', label: \'adresse\'}\n - {property: \'metro_station\', label: \'Station de m\xc3\xa9tro\'}\n - {property: \'location_coordinates\', label: \'Coordonn\xc3\xa9es\'}\nRun Code Online (Sandbox Code Playgroud)\n\n提前致谢。
\n我为一个非常有用的包 [VichUploader] 创建了一个解决方案,它缺少多个上传的功能,并且它适用于我在 [Symfony] 5.2 上创建的每个 Symfony 版本。它是 OneToMany 关系并且工作正常。所以我在我的自定义表单中使用了 CollectionType 和 [VichFileType],并在我的控制器中使用了一些小技巧,这里是代码并查看所有项目,您可以在我的GitHub
[链接] https://github.com/malek-中找到它拉蒂里
入学.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;
}
}
Run Code Online (Sandbox Code Playgroud)
文凭.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;
}
}
Run Code Online (Sandbox Code Playgroud)
入学类型.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,
]);
}
}
Run Code Online (Sandbox Code Playgroud)
文凭类型.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,
]);
}
}
Run Code Online (Sandbox Code Playgroud)
_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>
Run Code Online (Sandbox Code Playgroud)
脚本.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();
});
});
});
Run Code Online (Sandbox Code Playgroud)
控制器.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();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8514 次 |
| 最近记录: |