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

Twig 无法加载类型“;文件";在Symfony3中,twig,symfony,symfony-forms,vichuploaderbundle,Twig,Symfony,Symfony Forms,Vichuploaderbundle,我正在建立多个图像上传的形式,我无法找到解决问题的方法,在标题中提到。为了帮助我,我包括 现在我被这个错误所困扰,我无法找到代码中错误的原因和位置: Could not load type "file" 500 Internal Server Error - InvalidArgumentException 有人知道问题出在哪里吗 以下是我正在使用的代码: ProductType类别: <?php namespace AppBundle\Form\Type; use Symfony\

我正在建立多个图像上传的形式,我无法找到解决问题的方法,在标题中提到。为了帮助我,我包括

现在我被这个错误所困扰,我无法找到代码中错误的原因和位置:

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中删除了“文件”,错误消失了,但Twig无法呈现表单。此外,我还尝试使用self::class而不是“file”,这也没有帮助

//ProductImageType class
public function buildForm(FormBuilderInterface $builder, array $options)
    {
      $builder
         ->add('image')
     ;
    }
细枝模板中的结果:

<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:添加了细枝形式

{% 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 %}
{%extends'AppBundle::layout.html.twig%}
{%块样式表%}
{{parent()}}
{%endblock%}
{%block content%}
创造新的产品条件!
{{form_start(form,{'attr':{'class':'product form'}}}}
{%spaceless%}
{%如果不是form.vars.valid%}
{{form_errors(form)}}
{%为form.children%}
{%如果不是children.vars.valid%}
{{form_errors(children)}
{#或具有字段标签
    {%for children.vars.errors%中的错误}
  • {{children.vars.label}}:{{error.message}
  • {%endfor%}
#} {%endif%} {%endfor%} {%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)} 提交 {{form_end(form)}} {%endblock内容%}
以下是您应该如何将其添加到表单中:

use Symfony\Component\Form\Extension\Core\Type\FileType;

public function buildForm(FormBuilderInterface $builder, array $options)
{
     $builder->add('image', FileType::class);
}

在Symfony 3中,表单类型总是通过其完全限定的类名传递,下面是您应该如何将其添加到表单中:

use Symfony\Component\Form\Extension\Core\Type\FileType;

public function buildForm(FormBuilderInterface $builder, array $options)
{
     $builder->add('image', FileType::class);
}

在Symfony 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
}
3) 上传将使用上传服务完成,如所述。因此,设置希望文件进入
config.yml
的目录(不要在
parameters.yml
中设置此参数,因为如果推送项目,git会忽略此文件)

4) 声明服务

#app/config/services.yml
services:
    app.img_upload:
        class: AppBundle\Services\FileUpload
        arguments: ['%upload_dir%']
#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;
    }
}
5) 创建服务

#app/config/services.yml
services:
    app.img_upload:
        class: AppBundle\Services\FileUpload
        arguments: ['%upload_dir%']
#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 %}
#app/Resource/views/default/index.html.twig
{%extends'base.html.twig%}
{%block body%}
{{form_start(form)}}
{{form_行(form.path)}
上载
{{form_end(form)}}
{%endblock%}

正如我所承诺的,我将向您提供一个小示例,说明如何创建一个多上传表单&如何从表单中获取数据,并将其从临时目录移动到所需目录,并将路径保存在数据库中

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
}
3) 上传将使用上传服务完成,如所述。因此,设置希望文件进入
config.yml
的目录(不要在
parameters.yml
中设置此参数,因为如果推送项目,git会忽略此文件)

4) 声明服务

#app/config/services.yml
services:
    app.img_upload:
        class: AppBundle\Services\FileUpload
        arguments: ['%upload_dir%']
#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;
    }
}
5) 创建服务

#app/config/services.yml
services:
    app.img_upload:
        class: AppBundle\Services\FileUpload
        arguments: ['%upload_dir%']
#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 %}
#app/Resource/views/default/index.html.twig
{%extends'base.html.twig%}
{%block body%}
{{form_start(form)}}
{{form_行(form.path)}
上载
{{form_end(form)}}
{%endblock%}


@Veve在ProductImageType类中?@Veve我试过了,现在我的表单是空的。它甚至不会渲染。我也尝试过使用self::class,但它仍然不适用于Symfony 3,Symfony 3是在
ProductImageType.php
中添加的字段,我想它应该是
FileType
类型(需要导入),而且不是
文件类型
@DanCostinel我尝试了你的建议,我得到的结果与我在编辑后的段落中包含的结果相同。
VichUploaderBundle
bundle是你的项目的要求吗?如果没有,我可以为您提供一个多上传功能代码的示例。@Veve在ProductImageType类中?@Veve我试过了,现在我的表单是空的。它甚至不会渲染。我也尝试过使用self::class,但它仍然不适用于Symfony 3,Symfony 3是在
ProductImageType.php
中添加的字段,我想它应该是
FileType
类型(需要导入),而且不是
文件类型
@DanCostinel我尝试了你的建议,我得到的结果与我在编辑后的段落中包含的结果相同。
VichUploaderBundle
bundle是你的项目的要求吗?如果没有,我可以提供一个多上传功能代码的例子。我试过了,但是我在Twig模板中遇到了一个有线问题。你可以在编辑段落下检查twig的结果,模板是什么?它是bootstrap_3_layout.html。twig表单模板文件类型应该以div中的类型文件呈现输入,仅此而已。这段html从何而来?我用twig文件编辑了我的帖子。我不知道为什么我会得到这个html代码。有没有