无法加载类型"文件"在Symfony3中

时间:2017-01-26 17:33:39

标签: twig symfony symfony-forms vichuploaderbundle

我正在使用多个图片上传构建表单,但我无法找到标题中提到的问题的解决方案。为了帮助我,我加入了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=&quot;form-group&quot;><label class=&quot;control-label required&quot;>__name__label__</label><div id=&quot;product_images___name__&quot;><div class=&quot;form-group&quot;><label class=&quot;control-label required&quot; for=&quot;product_images___name___image&quot;>Image</label><input type=&quot;text&quot; id=&quot;product_images___name___image&quot; name=&quot;product[images][__name__][image]&quot; required=&quot;required&quot; class=&quot;form-control&quot; /></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 %}

2 个答案:

答案 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中,表单类型始终由其完全限定的类名称

传递