我正在使用多个图片上传构建表单,但我无法找到标题中提到的问题的解决方案。为了帮助我,我加入了VichUploaderBundle
现在我遇到了这个错误,我无法找到代码中出错的原因和位置:
Could not load type "file"
500 Internal Server Error - InvalidArgumentException
有人知道问题出在哪里吗?
以下是我正在使用的代码:
ProductType类:
<?php
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Vich\UploaderBundle\Form\Type\VichFileType;
use AppBundle\Entity\Product;
class ProductType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title', TextType::class)
->add('content', TextType::class)
->add('price', TextType::class)
->add('categories')
->add('productCondition')
->add("images", CollectionType::class, array(
'entry_type' => ProductImageType::class,
'allow_add' => true,
'allow_delete' => true
)
);
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Product::class
));
}
}
ProductImageType类
<?php
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;
class ProductImageType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('image', 'file')
;
}
/**
* @param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => ProductImage::class
));
}
/**
* @return string
*/
public function getName()
{
return 'product_image';
}
}
services.yml
# Learn more about services, parameters and containers at
# http://symfony.com/doc/current/service_container.html
parameters:
# parameter_name: value
services:
# service_name:
# class: AppBundle\Directory\ClassName
# arguments: ["@another_service_name", "plain_value", "%parameter_name%"]
app.form.type.file:
class: AppBundle\Form\Type\ProductImageType
tags:
- { name: form.type }
修改
我删除了文件&#39;从ProductImageType和错误消失但Twig无法呈现表单。我还尝试使用self :: class而不是&#39; file&#39;这也没有帮助。
//ProductImageType class
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('image')
;
}
Twig模板中的结果:
<div class="form-group">
<label class="control-label required">Images</label>
<div id="product_images" data-prototype="<div class="form-group"><label class="control-label required">__name__label__</label><div id="product_images___name__"><div class="form-group"><label class="control-label required" for="product_images___name___image">Image</label><input type="text" id="product_images___name___image" name="product[images][__name__][image]" required="required" class="form-control" /></div></div></div>"></div>
</div>
编辑2:添加了Twig表格
{% extends 'AppBundle::layout.html.twig' %}
{% block stylesheets %}
{{ parent() }}
<link href="{{ asset('/assets/vendor/components-font-awesome/css/font-awesome.min.css') }}" rel="stylesheet">
<link href="{{ asset('assets/css/form-elements.css') }}" rel="stylesheet">
<link href="{{ asset('assets/css/forms.css') }}" rel="stylesheet">
{% endblock %}
{% block content %}
<div class="top-content">
<div class="inner-bg">
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="form-box">
<div class="form-top">
<div class="form-top-left">
<h3>Create new product condition!</h3>
</div>
<div class="form-top-right">
<i class="fa fa-plus"></i>
</div>
</div>
<div class="form-bottom">
{{ form_start(form, { 'attr': {'class': 'product-form'} }) }}
{% spaceless %}
{% if not form.vars.valid %}
<div class="alert alert-error">
{{ form_errors(form) }}
{% for children in form.children %}
{% if not children.vars.valid %}
{{ form_errors(children) }}
{# or with field label
<ul>
{% for error in children.vars.errors %}
<li><b>{{ children.vars.label }}</b>: {{ error.message }}</li>
{% endfor %}
</ul>
#}
{% endif %}
{% endfor %}
</div>
{% endif %}
{% endspaceless %}
{{ form_row(form.title) }}
{{ form_row(form.content) }}
{{ form_row(form.price) }}
{{ form_row(form.categories) }}
{{ form_row(form.productCondition) }}
{{ form_row(form.images) }}
<button type="submit" class="btn">Submit!</button>
{{ form_end(form) }}
</div>
</div>
</div>
</div>
{% endblock content %}
答案 0 :(得分:3)
正如我所承诺的那样,我为您提供了一个如何创建多重上传表格的例子。如何从表单中获取数据并将其从临时目录移动到所需的数据,并将路径保存在数据库中。
1)创建实体类。
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Table(name="galleries")
* @ORM\Entity(repositoryClass="AppBundle\Repository\GalleryRepository")
*/
class Gallery
{
/**
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\Column(name="path", type="string", length=255)
*/
private $path;
// getter for $id, setter & getter for $path here
}
2)创建表格。
use Symfony\Component\Form\Extension\Core\Type\FileType;
//...
$builder->add('path', FileType::class, [
'data_class' => null,
'multiple' => true,
'label' => false
]);
3)上传将使用here之类的上传服务完成。因此,在config.yml
中设置您希望文件进入的目录(不要在parameters.yml
中设置此参数,因为如果您推送项目,git会忽略此文件。)
#app/config/config.yml
parameters:
upload_dir: '%kernel.root_dir%/../web/upload'
4)宣布服务。
#app/config/services.yml
services:
app.img_upload:
class: AppBundle\Services\FileUpload
arguments: ['%upload_dir%']
5)创建服务。
#AppBundle\Services\FileUpload.php
namespace AppBundle\Services;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class FileUpload
{
private $targetDir;
public function __construct($targetDir)
{
$this->targetDir = $targetDir;
}
public function upload(UploadedFile $file)
{
$file_name = $file->getClientOriginalName();
empty($file_name) ? $file_name = md5(uniqid()).'.'.$file->guessExtension() : $file_name = $file->getClientOriginalName();
$file->move($this->targetDir, $file_name);
return $file_name;
}
}
6)在控制器中创建整个逻辑。
#AppBundle/Controller/DefaultController.php
namespace AppBundle\Controller;
//...
use AppBundle\Entity\Gallery;
use AppBundle\Form\GalleryType;
//class...
/**
* @Route("/", name="homepage")
*/
public function indexAction(Request $request)
{
$gallery = new Gallery();
$form = $this->createForm(GalleryType::class, $gallery, [
'action'=>$this->generateUrl('homepage'),
'method'=>'POST'
]);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$paths = $form->get('path')->getData();
foreach ($paths as $path){
$img = $this->get('app.img_upload')->upload($path);
$em = $this->getDoctrine()->getConnection();
$stmt = $em->prepare('INSERT INTO galleries SET path=?');
$stmt->execute([$img]);
// THIS IS THE PROBLEM I ENCOUNTER! I COULDN'T USE NORMAL DOCTRINE WAY TO SAVE EACH IMAGE PATH INTO THE DB. KNOW THE FIX? POST IT HERE PLEASE!
// $em = $this->getDoctrine()->getManager();
// $em->persist($gallery);
// $em->flush();
//LE: I've found the "bug": you need to instantiate, for each $path, a new $gallery object, then set the data for it, + persist & flush.
}
$this->addFlash('success', 'The image(s) were successfully uploaded');
return $this->redirectToRoute('homepage');
}
return $this->render('default/index.html.twig', ['form'=>$form->createView()]);
}
7)最后,显示表格。
# app/Resource/views/default/index.html.twig
{% extends 'base.html.twig' %}
{% block body %}
{{ form_start(form) }}
{{ form_row(form.path) }}
<button type="submit" title="Upload an image">
Upload
</button>
{{ form_end(form) }}
{% endblock %}
答案 1 :(得分:1)
以下是将其添加到表单的方法:
use Symfony\Component\Form\Extension\Core\Type\FileType;
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('image', FileType::class);
}
在Symfony 3中,表单类型始终由其完全限定的类名称
传递