Ayhem
Ayhem

Reputation: 247

Upload image in symfony form

I am having a weird problem. I added an upload image field to a form. Every thing work fine when i use this code in the twig file

{{ form_start(form) }}
<button>d</button>
{{ form_end(form) }}

But when ever i want to use form_widget to costumize the look of the form this error appear when ever i try to sumit the form

FatalErrorException Error: Call to a member function getFileName() on string.

This is the View that cause the problem

{% extends 'BridgeTravelBundle:Admin:layout.html.twig' %}

{% block body %}
    <div class="col-md-12 col-sm-12 col-xs-12">
        <div class="x_panel">
            <form method="POST" id="demo-form2" data-parsley-validate class="form-horizontal form-label-left">
                <div class="form-group">
                    <label class="control-label col-md-3 col-sm-3 col-xs-12">Nom</span>
                    </label>
                    <div class="col-md-6 col-sm-6 col-xs-12">
                        {{ form_widget(form.name, { 'attr': {'class': 'form-control', 'placeholder': 'Prenom' } }) }}
                        {{ form_errors(form.name) }}
                    </div>
                </div>

                <div class="form-group">
                    <label class="control-label col-md-3 col-sm-3 col-xs-12">Icon</span>
                    </label>
                    <div class="col-md-6 col-sm-6 col-xs-12">
                        {{ form_widget(form.icon, { 'attr': {'class': 'form-control', 'placeholder': 'Prenom' } }) }}
                        {{ form_errors(form.icon) }}
                    </div>
                </div>

                <div class="form-group">
                    <label class="control-label col-md-3 col-sm-3 col-xs-12">Icon</span>
                    </label>
                    <div class="col-md-6 col-sm-6 col-xs-12">
                        {{ form_widget(form.file) }}
                        {{ form_errors(form.file) }}
                    </div>
                </div>

                <div class="ln_solid"></div>
                <div class="form-group">
                    <div class="col-md-6 col-sm-6 col-xs-12 col-md-offset-3">
                        <button class="btn btn-success">Valider</button>
                    </div>
                </div>

            </form>
        </div>
    </div>
{% endblock body %}

This is the Action that control the form.

public function addCategoryAction(Request $request){

        $category=new Category();
        $form=$this->createForm(CategoryType::class,$category);
        $form->handleRequest($request);

        if ($form->isSubmitted())
        {
            $image= $form['file']->getData();
            $em=$this->getDoctrine()->getManager();
            $req = $request->request->get('Bridge_TravelBundle_Category');
            $category->setName($req['name']);
            $category->setIcon($req['icon']);
            $name = $req['name'];
            try {
                if(!is_dir("CategoriesPictures")){
                    mkdir("CategoriesPictures");
                }

                move_uploaded_file($image,"CategoriesPictures/".$image->getFileName());
                rename("CategoriesPictures/".$image->getFileName() , "CategoriesPictures/".$name.".jpg");

            }
            catch (IOExceptionInterface $e) {
                echo "Erreur Profil existant ou erreur upload image ".$e->getPath();
            }

            $em->persist($category);
            $em->flush();
            return $this->redirectToRoute('admin_categories');
        }

        return $this->render("BridgeTravelBundle:Admin:addcategory.html.twig",array('form' => $form->createView(),));
    }

This the CategoryType.php

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class CategoryType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('name')
            ->add('icon')
            ->add('file',FileType::class, array(
                    'multiple'    => false,
                    'attr' => array(

                        'accept' => 'image/*',
                    )
                )
            )       ;
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Bridge\TravelBundle\Entity\Category'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'Bridge_TravelBundle_Category';
    }
}

Upvotes: 1

Views: 4997

Answers (1)

HoangND
HoangND

Reputation: 408

This attribute enctype='multipart/form-data' is missing from your form tag.

You should just you form_start & form_end instead writing form tag by yourself.

You can also put custom attributes with form_start function like this

{{ form_start(form, { 'attr': {'class': 'foo', 'id': 'bar' } }) }} 

Also, form_end is very important because it also print out form_rest and any missing field.

<form method="POST" id="demo-form2" data-parsley-validate class="form-horizontal form-label-left">

will become

{{ form_start(form, { 'attr': { 'id': 'demo-form2', 'data-parsley-validate': null, 'class': 'form-horizontal form-label-left' } }) }}

and

</form>

will become

{{ form_end(form) }}

Upvotes: 4

Related Questions