title: Upload file in Symfony2: Catchable Fatal Error: Argument 1 passed to
body: <p>I work with <strong>Symfony2 and wamp server</strong>. I try to implement the <strong>upload method</strong> following the <a href="http://symfony.com/fr/doc/2.5/cookbook/doctrine/file_uploads.html" rel="nofollow">Symfony doc/cookbook</a>.</p>
  
  <p>I I have two <strong>entities</strong>: <code>DocumentsEnsemble.php</code> and <code>Ensembles.php</code>. DocumentsEnsembles is the entity where I <strong>store uploading files</strong> for <strong>1</strong> ensemble (image, doc, pdf etc...). An <strong>Ensemble</strong> can have <strong>0 or many</strong> documents, and a <strong>document</strong> can belong <strong>to 0 or 1 single</strong> Ensemble.</p>
  
  <p>This is my Ensembles entity code named <code>Ensembles.php</code> :</p>
  
  <pre><code>namespace MySpace\DatabaseBundle\Entity;
  
  use Doctrine\ORM\Mapping as ORM;
  use Symfony\Component\Validator\Constraints as Assert;
  use Symfony\Component\HttpFoundation\File\UploadedFile;
  
  /**
   * Ensembles
   *
   * @ORM\Table(name="ensembles")
   * @ORM\Entity
   */
  class Ensembles
  {
      /**
       * @var integer
       *
       * @ORM\Column(name="id", type="integer", nullable=false)
       * @ORM\Id
       * @ORM\GeneratedValue(strategy="IDENTITY")
       */
      private $id;
  
      /**
      * @var string
      *
      * @ORM\Column(name="nom", type="string", length=150, nullable=false)
      */
      private $nom;
  
      /**
      * @ORM\ManyToOne(targetEntity="Documentsensemble", inversedBy="file")
      * @ORM\JoinColumn(name="documentsensemble_id", referencedColumnName="id", nullable=true)
      */
      private $documentsensemble;
  
     //the getters and setters
  
    //implement Upload method
  public function preUpload()
      {
          if (null !== $this-&gt;file) {
              $this-&gt;path = sha1(uniqid(mt_rand(), true)).'.'.$this-&gt;file-&gt;guessExtension();
          }
      }
  
      /**
       * @ORM\PostPersist()
       * @ORM\PostUpdate()
       */
      public function upload()
      {
          if (null === $this-&gt;file) {
              return;
          }
          $this-&gt;file-&gt;move($this-&gt;getUploadRootDir(), $this-&gt;path);
  
          unset($this-&gt;file);
      }
  
      /**
       * @ORM\PostRemove()
       */
      public function removeUpload()
      {
          if ($file = $this-&gt;getAbsolutePath()) {
              unlink($file);
          }
      }
  </code></pre>
  
  <p>I would like to implement the upload method like you can see in Ensembles. And this is the DocumentsEnsemble entity named <code>DocumentsEnsembles.php</code>:</p>
  
  <pre><code>namespace MySpace\DatabaseBundle\Entity;
  
  use Doctrine\ORM\Mapping as ORM;
  use Symfony\Component\Validator\Constraints as Assert;
  use Symfony\Component\HttpFoundation\File\UploadedFile;
  
  /**
   * Documentsensemble
   *
   * @ORM\Table(name="documentsensemble")
   * @ORM\Entity
   * @ORM\HasLifecycleCallbacks
   */
  class Documentsensemble
  {
  /**
   * @var integer
   *
   * @ORM\Column(name="id", type="integer", nullable=false)
   * @ORM\Id
   * @ORM\GeneratedValue(strategy="IDENTITY")
   */
  private $id;
  
  /**
   * @ORM\Column(type="string", length=255)
   * @Assert\NotBlank
   */
  public $nom;
  
  /**
       * @ORM\Column(type="string", length=255, nullable=true)
       */
      public $path; //La propriété path stocke le chemin relatif du fichier et est persistée dans la base de données
  
      public function getAbsolutePath()
      {
          return null === $this-&gt;path ? null : $this-&gt;getUploadRootDir().'/'.$this-&gt;path;
      }
  
      public function getWebPath()
      {
          return null === $this-&gt;path ? null : $this-&gt;getUploadDir().'/'.$this-&gt;path;
      }
  
      protected function getUploadRootDir()
      {
          return __DIR__.'src/MySpace/WelcomeBundle/Ressources/public/image/uploadEnsembles'.$this-&gt;getUploadDir();
      }
  
      protected function getUploadDir()
      {
          return 'uploads/documents';
      }
  
      /**
       * @Assert\File(maxSize="4M")
       * @ORM\OneToMany(targetEntity="Ensembles", mappedBy="documentsensemble")
       */
      public $file;
  
     // the getters and setters
  </code></pre>
  
  <p>In a form with post method, I can add an ensemble in my Ensembles entity. This form contain the input file to upload files belong to an ensemble. I use a form generate by Doctrine named <code>EnsemblesType.php</code>, this is the code for:</p>
  
  <pre><code>namespace MySpace\DatabaseBundle\Form;
  
  use Symfony\Component\Form\AbstractType;
  use Symfony\Component\Form\FormBuilderInterface;
  use Symfony\Component\OptionsResolver\OptionsResolverInterface;
  
  class EnsemblesType extends AbstractType
  {
      /**
       * @param FormBuilderInterface $builder
       * @param array $options
       */
      public function buildForm(FormBuilderInterface $builder, array $options)
      {
          $builder
              -&gt;add('referenceclient')
              -&gt;add('nom')
              -&gt;add('voie')
              -&gt;add('numerovoie')
              -&gt;add('codepostal')
              -&gt;add('commune')
              -&gt;add('dateactivation','date', array(
                      'widget' =&gt; 'single_text',
                      'format' =&gt; 'yyyy-MM-dd',
                      'attr' =&gt; array('class' =&gt; 'datepicker')
                      ))
              -&gt;add('datedesactivation', 'date', array(
                      'widget' =&gt; 'single_text',
                      'format' =&gt; 'yyyy-MM-dd',
                      'attr' =&gt; array('class' =&gt; 'datepicker')
                      ))
              -&gt;add('documentsensemble', 'file')
              -&gt;add('parcsimmobilier')
              -&gt;add('systemes')
          ;
      }
  
      /**
       * @param OptionsResolverInterface $resolver
       */
      public function setDefaultOptions(OptionsResolverInterface $resolver)
      {
          $resolver-&gt;setDefaults(array(
              'data_class' =&gt; 'MySpace\DatabaseBundle\Entity\Ensembles'
          ));
      }
  
      /**
       * @return string
       */
      public function getName()
      {
          return 'MySpace_databasebundle_ensembles';
      }
  }
  </code></pre>
  
  <p>And this is my <code>addEnsembles.html.twig</code> with the form with the post method:</p>
  
  <pre><code>&lt;form action="{{ path('ajouterEnsembles_process') }}" method="post" {{ form_enctype(formEnsemble) }}&gt;
    {{ form_errors(formEnsemble) }}   
    &lt;div&gt;
      {{ form_label(formEnsemble.nom, "Nom de l'ensemble:", {'label_attr': {'class': 'control-label'}}) }}
      {{ form_errors(formEnsemble.nom) }}
      &lt;div&gt;
        {{ form_widget(formEnsemble.nom, {'attr': {'class': 'form-control'}}) }}
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;br&gt;
    {# Upload #}
    &lt;div class="container"&gt;
      &lt;div class="row col-md-12"&gt;
        &lt;div class="row col-md-9"&gt;
         {{ form_label(formEnsemble.documentsensemble, "Transférer un fichier appartenant à cet ensemble:", {'label_attr': {'class': 'control-label'}}) }}
          &lt;div&gt;
           {{ form_widget(formEnsemble.documentsensemble) }}
          &lt;/div&gt;
        &lt;/div&gt;
        &lt;br&gt;
        {# validation #}
        &lt;div class="row col-md-3"&gt;
          &lt;input type="submit" value="Ajouter" class="btn btn-success"/&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/form&gt;
  </code></pre>
  
  <p>When I submit my form, I Have this error:</p>
  
  <blockquote>
    <p>Catchable Fatal Error: Argument 1 passed to
    MySpace\DatabaseBundle\Entity\Ensembles::setDocumentsensemble() must
    be an instance of MySpace\DatabaseBundle\Entity\Documentsensemble,
    instance of Symfony\Component\HttpFoundation\File\UploadedFile given,
    called in
    C:\wamp\www\BitbucketRepository\repos\SymfonyGirusMySpace\vendor\symfony\symfony\src\Symfony\Component\PropertyAccess\PropertyAccessor.php
    on line 438 and defined in
    C:\wamp\www\BitbucketRepository\repos\SymfonyGirusMySpace\src\MySpace\DatabaseBundle\Entity\Ensembles.php
    line 411</p>
  </blockquote>
  
  <p>Someone could explain me in order to find the right solution? Am I doing right for the uploading file method?</p>
  
  <p>This my controller method to add an Ensemble with an uploaded file: </p>
  
  <pre><code>public function addEnsemblesAction() {
  
          $em=$this-&gt;getDoctrine()-&gt;getManager();
          $ensemble = new Ensembles;
          $formEnsemble=$this-&gt;createForm(new EnsemblesType(), $ensemble);
  
          $request = $this-&gt;getRequest();
  
              if ($request-&gt;isMethod('POST') | ($formEnsemble-&gt;isValid())) {
  
                      $formEnsemble-&gt;bind($request);
                      $ensemble = $formEnsemble-&gt;getData();
  
                      $em-&gt;persist($ensemble);
                      $em-&gt;flush();
  
                      return $this-&gt;redirect($this-&gt;generateUrl('showEnsembles'));
                  }
  
              else {
                      return $this-&gt;render('MySpaceGestionPatrimoinesBundle:Ensembles:addrEnsembles.html.twig', array('formEnsemble' =&gt; $formEnsemble-&gt;createView() ));
                   }
  
  }
  </code></pre>
  
  <hr>
  
  <p>UPDATE QUESTION FOR SOLUTION</p>
  
  <h2><em>thanks to the answer and the comments of Abdallah Arffak</em></h2>
  
  <p>In fact I change the relation between my 2 entites. Indeed the upload method have to be in Documentsensemble.php.</p>
  
  <p>This is the code for <code>Ensembles.php</code> :</p>
  
  <pre><code>namespace MySpace\DatabaseBundle\Entity;
  
  use Doctrine\ORM\Mapping as ORM;
  use Symfony\Component\Validator\Constraints as Assert;
  use Symfony\Component\HttpFoundation\File\UploadedFile;
  
  /**
   * Ensembles
   *
   * @ORM\Table(name="ensembles")
   * @ORM\Entity
   */
  class Ensembles
  {
      /**
       * @var integer
       *
       * @ORM\Column(name="id", type="integer", nullable=false)
       * @ORM\Id
       * @ORM\GeneratedValue(strategy="IDENTITY")
       */
      private $id;
  
      /**
      * @var string
      *
      * @ORM\Column(name="nom", type="string", length=150, nullable=false)
      */
      private $nom;
  
      // The getters and setters
  </code></pre>
  
  <p>Now the code for <code>Documentsensembles.php</code> with upload method (callbacks etc...):</p>
  
  <pre><code>namespace MySpace\DatabaseBundle\Entity;
  
  use Doctrine\ORM\Mapping as ORM;
  use Symfony\Component\Validator\Constraints as Assert;
  use Symfony\Component\HttpFoundation\File\UploadedFile;
  
  /**
   * Documentsensemble
   *
   * @ORM\HasLifecycleCallbacks
   * @ORM\Table(name="documentsensemble", indexes={@ORM\Index(name="IDX_674FC05E5BA556D3", columns={"ensembles_id"})})
   * @ORM\Entity
   */
  class Documentsensemble
  {
      /**
       * @var integer
       *
       * @ORM\Column(name="id", type="integer", nullable=false)
       * @ORM\Id
       * @ORM\GeneratedValue(strategy="IDENTITY")
       */
      private $id;
  
      /**
       * @var string
       *
       * @ORM\Column(name="nom", type="string", length=255, nullable=false)
       * @Assert\NotBlank
       */
      private $nom;
  
      /**
       * @var string
       *
       * @ORM\Column(name="path", type="string", length=255, nullable=true)
       */
      private $path; //stocke le chemin relatif du fichier et est persistée dans la base de données
  
  
      /**
      * @Assert\File(maxSize="6000000")
      */
      public $file;
  
      // UPLOAD
          public function getWebPath()
          {
              return null === $this-&gt;path ? null : $this-&gt;getUploadDir().'/'.$this-&gt;path;
          }
  
          protected function getUploadRootDir()
          {
              // le chemin absolu du répertoire où les documents uploadés doivent être sauvegardés
              return __DIR__.'/../../../../MySpace/'.$this-&gt;getUploadDir();
          }
  
          protected function getUploadDir()
          {
              // on se débarrasse de « __DIR__ » afin de ne pas avoir de problème lorsqu'on affiche le document/image dans la vue.
              return 'uploads/documentsEnsemble';
          }
  
          // propriété utilisé temporairement pour la suppression
          private $filenameForRemove;
  
          /**
           * @ORM\PrePersist()
           * @ORM\PreUpdate()
           */
          public function preUpload()
          {
              if (null !== $this-&gt;file) {
                  $this-&gt;path = $this-&gt;file-&gt;guessExtension();
              }
          }
  
          /**
           * @ORM\PostPersist()
           * @ORM\PostUpdate()
           */
          public function upload()
          {
              if (null === $this-&gt;file) {
                  return;
              }
  
              // lancer une exception ici si le fichier ne peut pas être déplacé afin que l'entité ne soit pas persistée dans la base de données comme le fait la méthode move() de UploadedFile
              $this-&gt;file-&gt;move($this-&gt;getUploadRootDir(), $this-&gt;nom.'.'.$this-&gt;file-&gt;guessExtension());
  
              unset($this-&gt;file);
          }
  
          /**
           * @ORM\PreRemove()
           */
          public function storeFilenameForRemove()
          {
              $this-&gt;filenameForRemove = $this-&gt;getAbsolutePath();
          }
  
          /**
           * @ORM\PostRemove()
           */
          public function removeUpload()
          {
              if ($this-&gt;filenameForRemove) {
                  unlink($this-&gt;filenameForRemove);
              }
          }
  
          public function getAbsolutePath()
          {
              return null === $this-&gt;path ? null : $this-&gt;getUploadRootDir().'/'.$this-&gt;nom.'.'.$this-&gt;path = $this-&gt;file-&gt;guessExtension();
          }
          // The getters and the setters
  </code></pre>
  
  <p>and now the code for controller:</p>
  
  <pre><code>public function uploadAction() {
  
          $message = "Infos: aucun documents uploadé présent pour le moment";
          $em=$this-&gt;getDoctrine()-&gt;getManager();
          $documentsensemble = $em-&gt;getRepository('MySpaceDatabaseBundle:Documentsensemble');
  
          $documentsensemble = new Documentsensemble();
          $formUpload = $this-&gt;createForm(new DocumentsensembleType(), $documentsensemble);
  
  
          $requestUpload = $this-&gt;getRequest();
  
          //instruction if à plusieurs conditions: ici si la method est POST et si le formulaire est valide
          if ($requestUpload-&gt;isMethod('POST') | ($formUpload-&gt;isValid())) {
  
                  $formUpload-&gt;bind($requestUpload);
                  $documentsensemble = $formUpload-&gt;getData();
                  //$documentsensemble-&gt;upload();
                  //Cette ligtne est commenté car nous utilisons les callbacks pour la méthode Upload de Symfony
  
                  $em-&gt;persist($documentsensemble);
                  $em-&gt;flush();
  
                  return $this-&gt;redirect($this-&gt;generateUrl('MySpace_formulaire_recherche_ensembles'));
              }
  
          //retourner le formulaire d'ajout si c'est invalide
          else {
                  return $this-&gt;render('MySpaceGestionPatrimoinesBundle:Ensembles:documentsensemble.html.twig', array('formUpload' =&gt; $formUpload-&gt;createView(), 'message' =&gt; $message ));
               }
  
      }
  </code></pre>
  
  <p>Finally, I call the form in a twig in another form, there are so many methods and ways to do this, check <a href="http://symfony.com/doc/master/cookbook/form/form_collections.html" rel="nofollow">the symfony cookbook</a> or <a href="http://symfony.com/doc/current/cookbook/doctrine/registration_form.html" rel="nofollow">here</a> for example like Abdallah Arffak suggests me.</p>
  
  <p>Thank you a lot and sorry if my english is bad.</p>