无法加载类型“文件"在 Symfony3 中 [英] Could not load type "file" in Symfony3

查看:11
本文介绍了无法加载类型“文件"在 Symfony3 中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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 class:

<?php

namespace AppBundleFormType;

use SymfonyComponentFormAbstractType;
use SymfonyComponentFormFormBuilderInterface;
use SymfonyComponentOptionsResolverOptionsResolver;
use SymfonyComponentFormExtensionCoreTypeCollectionType;
use SymfonyComponentFormExtensionCoreTypeTextType;
use VichUploaderBundleFormTypeVichFileType;
use AppBundleEntityProduct;



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 class

<?php

namespace AppBundleFormType;

use SymfonyComponentFormAbstractType;
use SymfonyComponentFormFormBuilderInterface;
use SymfonyComponentOptionsResolverOptionsResolverInterface;
use SymfonyComponentFormExtensionCoreTypeTextType;


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: AppBundleDirectoryClassName
#        arguments: ["@another_service_name", "plain_value", "%parameter_name%"]
    app.form.type.file:
        class: AppBundleFormTypeProductImageType
        tags:
            - { name: form.type }

EDIT:

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')
     ;
    }

Results in Twig template:

<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>

EDIT 2: added Twig form

{% 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 %}

解决方案

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) Create the Entity class.

<?php
namespace AppBundleEntity;
use DoctrineORMMapping as ORM;
/**
 * @ORMTable(name="galleries")
 * @ORMEntity(repositoryClass="AppBundleRepositoryGalleryRepository")
 */
class Gallery
{
    /**
     * @ORMColumn(name="id", type="integer")
     * @ORMId
     * @ORMGeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORMColumn(name="path", type="string", length=255)
     */
    private $path;

    // getter for $id, setter & getter for $path here
}

2) Create the Form.

use SymfonyComponentFormExtensionCoreTypeFileType;
//...
$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) Declare the service.

#app/config/services.yml
services:
    app.img_upload:
        class: AppBundleServicesFileUpload
        arguments: ['%upload_dir%']

5) Create the service.

#AppBundleServicesFileUpload.php

namespace AppBundleServices;

use SymfonyComponentHttpFoundationFileUploadedFile;

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) Create the whole logic in the controller.

#AppBundle/Controller/DefaultController.php

namespace AppBundleController;
//...
use AppBundleEntityGallery;
use AppBundleFormGalleryType;
//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) 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆