2

I have the following error: "Argument 1 passed to App\Service\FileUploader::upload() must be an instance of Symfony\Component\HttpFoundation\File\UploadedFile, string given"

I applied the solution found in this post but it did not change anything. Quite normal, it's not excactly the same error. Can anyone help me please ?

My goal here is to attach multiple documents to a company from the company screen.

I have been trying to solve the problem since yesterday morning. Now, it's time for me to make a break away from keyboard for 1 or 2 hours ...

Here is the code:

Document entity

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\DocumentRepository")
 */
class Document
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $fichier;

    /**
     * @var UploadedFile
     */
    private $file;

    // ...
}

Entreprise entity

namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\EntrepriseRepository")
 */
class Entreprise
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Document", mappedBy="entreprise", orphanRemoval=true, cascade={"persist"})
     */
    private $documents;

    // ...

    public function __construct()
    {
        $this->documents = new ArrayCollection();
    }

    // ...

    public function getDocuments()
    {
        return $this->documents;
    }

    public function addDocument(Document $document)
    {
        if (!$this->documents->contains($document)) {
            $this->documents[] = $document;
            //...
        }

        return $this;
    }

    public function removeDocument(Document $document)
    {
        if ($this->documents->contains($document)) {
            $this->documents->removeElement($document);
        }

        return $this;
    }
}

Entreprise Form Typenamespace App\Form\Type;

use App\Entity\Entreprise;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\FileType;

use Symfony\Bridge\Doctrine\Form\Type\EntityType;

class EntrepriseType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('documents', CollectionType::class, [
                'entry_type' => DocumentType::class,
                'entry_options' => ['label' => false],
                'allow_add' => true,
                'by_reference' => false,
                'allow_delete' => true,
                ])
            // ...
            ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Entreprise::class,
        ]);
    }
}

Entreprise Controller

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\Routing\Annotation\Route;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\HttpFoundation\Request;

use App\Entity\Entreprise;
use App\Form\Type\EntrepriseType;
use App\Repository\EntrepriseRepository;
use App\Service\FileUploader;

class EntrepriseController extends AbstractController
{
    /**
     * @Route("/entreprise/{id}", name="entreprise_detail")
     * @Route("/entreprise/new", name="entreprise_new")
     */
    public function index(Entreprise $entreprise = null, Request $request, ObjectManager $manager, FileUploader $fileUploader)
    {
        if (!$entreprise) {
            $entreprise = new Entreprise();
        }

        $formDetail = $this->createForm(EntrepriseType::class, $entreprise);
        $formDetail->handleRequest($request);

        if ($formDetail->isSubmitted() && $formDetail->isValid()) {
            $this->setDefault($entreprise);

            // Téléchargement des nouveaux documents rattachés à l'entreprise
            $documents = $entreprise->getDocuments();
            foreach ($documents as $document) {
                if (!$document->getId()){
                    /** @var Symfony\Component\HttpFoundation\File\UploadedFile $file */
                    $file = $document->getFile();

                    $document->setFichier($fileUploader->upload($file));
                }
            }

            // Mise à jour de la base de données
            $manager->persist($entreprise);
            $manager->flush();

            return $this->redirectToRoute('entreprise_detail', ['id'=> $entreprise->getId()]);
        }

        return $this->render('entreprise/index.html.twig', [
            'formDetail' => $formDetail->createView(),
            'entreprise' => $entreprise,
        ]);
    }
    // ...
}

PS : Sorry if my english is not good enough but if you want, you can answer in french.

1 Answer 1

5

I had the same issue and solved it by removing the type casting in the getFile() and setFile() in the entity. I suppose this is located in your Document entity.

Look for:

public function getFile(): ?string
{
    return $this->file;
}

public function setFile(string $file): self
{
    $this->file = $file;

    return $this;
}

and replace it with

public function getFile()
{
    return $this->file;
}

public function setFile($file): self
{
    $this->file = $file;

    return $this;
}

This will make sure that the file property will have an Instance of the UploadedFile class instead of invoking the __toString method of the same class (due to casting of type to string).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.