无法加载“文件"类型在Symfony3中 [英] Could not load type "file" in Symfony3
问题描述
我正在构建具有多个图像上传功能的表单,但找不到标题中提到的问题的解决方案.为了帮助我,我添加了 VichUploaderBundle
I am building form with multiple image upload and I can't find solution for problem that is mentioned in title. To help me with that I included VichUploaderBundle
现在,我被这个错误困住了,我找不到代码错误的原因和位置:
Right now I am stuck with this error and I can't find why and where is mistake in code:
Could not load type "file"
500 Internal Server Error - InvalidArgumentException
有人知道问题出在哪里吗?
Does someone knows where is the problem?
这是我正在使用的代码:
Here is code that I am using:
ProductType类:
ProductType class:
<?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类
ProductImageType class
<?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
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 }
我从ProductImageType中删除了文件",但错误消失了,但Twig无法呈现表单.我也尝试使用self :: class而不是'file',但这也没有帮助.
I removed 'file' from ProductImageType and error is gone but Twig fails to render a form. Also I tried to use self::class instead of 'file' and that didn't helped either.
//ProductImageType class
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('image')
;
}
Twig模板中的结果:
Results in Twig template:
<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>
添加了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 %}
推荐答案
正如我所承诺的,我将向您提供一个示例,说明如何创建多次上传表格&如何从表单中获取数据并将其从temp目录移至所需目录,然后将路径保存在数据库中.
As I promised, I'm providing you a little example of how you can create a multiple-upload form & how to get the data from the form and move it from the temp directory to your desired one, and save the path in the database.
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) The upload will be done using an upload service like here is stated. So set the directory you want your file to go in config.yml
(don't set this parameter in parameters.yml
because this file is ignored by git, if you push the project).
#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)在控制器中创建整个逻辑.
6) Create the whole logic in the controller.
#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)最后,显示表单.
7) Finally, display the form.
# 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 %}
这篇关于无法加载“文件"类型在Symfony3中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!