Grechka Vassili
Grechka Vassili

Reputation: 883

The form's view data is expected to be an instance of class File, but is a(n) string

I'm trying to show a link to download an existing file in Symfony but I have the error which is in the Title.

I have a nursery that uploads her documents and after that I want to show them. I've made this part of the documentation : http://symfony.com/doc/current/form/create_form_type_extension.html. But it doesn't work for me ...

So, This is my Extension where we add 2 options to the form :

<?php

namespace VS\CrmBundle\Form\Extension;

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\PropertyAccess\PropertyAccess;

class DocumentTypeExtension extends AbstractTypeExtension
{

    /**
     * Returns the name of the type being extended.
     *
     * @return string The name of the type being extended
     */
    public function getExtendedType()
    {
        return FileType::class;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefined(array('doc_path', 'doc_name'));
    }

    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        if(isset($options['doc_path']))
        {
            $parentData = $form->getParent()->getData();

            $documentUrl = null;
            if(null !== $parentData)
            {
                $accessor = PropertyAccess::createPropertyAccessor();
                $documentUrl = $accessor->getValue($parentData, $options['doc_path']);
            }

            $view->vars['doc_path']-> $documentUrl;
        }

        if(isset($options['doc_name']))
        {
            $parentData = $form->getParent()->getData();

            $documentName = null;
            if(null !== $parentData)
            {
                $accessor = PropertyAccess::createPropertyAccessor();
                $documentName = $accessor->getValue($parentData, $options['doc_name']);
            }

            $view->vars['doc_name']-> $documentName;
        }
    }
}

Service Definition :

vs_crm.document_type_extension:
        class: VS\CrmBundle\Form\Extension\DocumentTypeExtension
        tags:
          - { name: form.type_extension, extended_type: Symfony\Component\Form\Extension\Core\Type\FileType }

View extension :

{% extends 'form_div_layout.html.twig' %}

{% block file_widget %}
    {% spaceless %}
        {% if (doc_path is not null) and (doc_name is not null) %}
            <a href="{{ asset(doc_path) }}">{{ doc_name }}</a>
        {% endif %}
    {% endspaceless %}
{% endblock %}

My Form :

<?php

namespace VS\CrmBundle\Form;

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

class NurseryDocumentsType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('docUrl', FileType::class, array(
                'label' => 'Choose a PDF file',
                'doc_path' => 'nurseryDocumentsPath',
                'doc_name' => 'docUrl'
            ))
            ->add('isMandatory')
            ->add('docType');
    }

And I've tried to call the form_widget several ways but unsuccessful...

what I don't realy understood from the documentation is : ok, the doc_name in the builForm is going to take my doc_url (whitch is the name of the file saved in the db) but what about the doc_path ? So I dit this (don't be rude :p) :

// NurseryDocuments entity
    /**
     * @return string|null
     */
    public function getNurseryDocumentPath()
    {
        return __DIR__.'/../../../web/static/documents/NurseryDocuments'.$this->docUrl;
    }

Little precisions : 1) I'm trying to show this documents in a step of a multi step form made with CraueFormBundle so I can't pass arguments from the controlle to my flow. 2) I've tried to make an action like :

public function showNurseryDocumentAction($document)
    {
        $path = $this->get('kernel')->getRootDir().'/../web/static/documents/NurseryDocuments/';
        $content = file_get_contents($path.$document);

        $response = new Response();

        $response->headers->set('Content-Type', 'mime/type');
        $response->headers->set('Content-Disposition', 'attachment;filename="'.$document);
        $response->setContent($content);

        return $response;
    }

This works in another context but here I have error ...

Complete error :

The form's view data is expected to be an instance of class Symfony\Component\HttpFoundation\File\File, but is a(n) string. You can avoid this error by setting the "data_class" option to null or by adding a view transformer that transforms a(n) string to an instance of Symfony\Component\HttpFoundation\File\File.

Thanks !

Upvotes: 0

Views: 2984

Answers (2)

Grechka Vassili
Grechka Vassili

Reputation: 883

Ok, I have made another form like :

<?php

namespace VS\CrmBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;

class NurseryDocumentsShowType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
                ->add('docUrl', TextType::class);
    }

    public function getParent()
    {
        return NurseryDocumentsType::class;
    }
}

That I use with the download method as you can see higher showNurseryDocumentAction($document). So I need one formType for the upload of documents and another to show/download them. Hope it can help someone.

Upvotes: 0

Gopal Joshi
Gopal Joshi

Reputation: 2358

Please Try after adding 'data_class' => null with docUrl in FormType.

NurseryDocumentsType.php

->add('docUrl', FileType::class, array(
    'label' => 'Choose a PDF file',
    'doc_path' => 'nurseryDocumentsPath',
    'doc_name' => 'docUrl',
    'data_class' => null
))

Upvotes: 3

Related Questions