简体   繁体   中英

Upload file in Symfony2: Catchable Fatal Error: Argument 1 passed to

I work with Symfony2 and wamp server . I try to implement the upload method following the Symfony doc/cookbook .

II have two entities : DocumentsEnsemble.php and Ensembles.php . DocumentsEnsembles is the entity where I store uploading files for 1 ensemble (image, doc, pdf etc...). An Ensemble can have 0 or many documents, and a document can belong to 0 or 1 single Ensemble.

This is my Ensembles entity code named Ensembles.php :

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->file) {
            $this->path = sha1(uniqid(mt_rand(), true)).'.'.$this->file->guessExtension();
        }
    }

    /**
     * @ORM\PostPersist()
     * @ORM\PostUpdate()
     */
    public function upload()
    {
        if (null === $this->file) {
            return;
        }
        $this->file->move($this->getUploadRootDir(), $this->path);

        unset($this->file);
    }

    /**
     * @ORM\PostRemove()
     */
    public function removeUpload()
    {
        if ($file = $this->getAbsolutePath()) {
            unlink($file);
        }
    }

I would like to implement the upload method like you can see in Ensembles. And this is the DocumentsEnsemble entity named DocumentsEnsembles.php :

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->path ? null : $this->getUploadRootDir().'/'.$this->path;
    }

    public function getWebPath()
    {
        return null === $this->path ? null : $this->getUploadDir().'/'.$this->path;
    }

    protected function getUploadRootDir()
    {
        return __DIR__.'src/MySpace/WelcomeBundle/Ressources/public/image/uploadEnsembles'.$this->getUploadDir();
    }

    protected function getUploadDir()
    {
        return 'uploads/documents';
    }

    /**
     * @Assert\File(maxSize="4M")
     * @ORM\OneToMany(targetEntity="Ensembles", mappedBy="documentsensemble")
     */
    public $file;

   // the getters and setters

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 EnsemblesType.php , this is the code for:

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
            ->add('referenceclient')
            ->add('nom')
            ->add('voie')
            ->add('numerovoie')
            ->add('codepostal')
            ->add('commune')
            ->add('dateactivation','date', array(
                    'widget' => 'single_text',
                    'format' => 'yyyy-MM-dd',
                    'attr' => array('class' => 'datepicker')
                    ))
            ->add('datedesactivation', 'date', array(
                    'widget' => 'single_text',
                    'format' => 'yyyy-MM-dd',
                    'attr' => array('class' => 'datepicker')
                    ))
            ->add('documentsensemble', 'file')
            ->add('parcsimmobilier')
            ->add('systemes')
        ;
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'MySpace\DatabaseBundle\Entity\Ensembles'
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'MySpace_databasebundle_ensembles';
    }
}

And this is my addEnsembles.html.twig with the form with the post method:

<form action="{{ path('ajouterEnsembles_process') }}" method="post" {{ form_enctype(formEnsemble) }}>
  {{ form_errors(formEnsemble) }}   
  <div>
    {{ form_label(formEnsemble.nom, "Nom de l'ensemble:", {'label_attr': {'class': 'control-label'}}) }}
    {{ form_errors(formEnsemble.nom) }}
    <div>
      {{ form_widget(formEnsemble.nom, {'attr': {'class': 'form-control'}}) }}
    </div>
  </div>
  <br>
  {# Upload #}
  <div class="container">
    <div class="row col-md-12">
      <div class="row col-md-9">
       {{ form_label(formEnsemble.documentsensemble, "Transférer un fichier appartenant à cet ensemble:", {'label_attr': {'class': 'control-label'}}) }}
        <div>
         {{ form_widget(formEnsemble.documentsensemble) }}
        </div>
      </div>
      <br>
      {# validation #}
      <div class="row col-md-3">
        <input type="submit" value="Ajouter" class="btn btn-success"/>
      </div>
    </div>
  </div>
</form>

When I submit my form, I Have this error:

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

Someone could explain me in order to find the right solution? Am I doing right for the uploading file method?

This my controller method to add an Ensemble with an uploaded file:

public function addEnsemblesAction() {

        $em=$this->getDoctrine()->getManager();
        $ensemble = new Ensembles;
        $formEnsemble=$this->createForm(new EnsemblesType(), $ensemble);

        $request = $this->getRequest();

            if ($request->isMethod('POST') | ($formEnsemble->isValid())) {

                    $formEnsemble->bind($request);
                    $ensemble = $formEnsemble->getData();

                    $em->persist($ensemble);
                    $em->flush();

                    return $this->redirect($this->generateUrl('showEnsembles'));
                }

            else {
                    return $this->render('MySpaceGestionPatrimoinesBundle:Ensembles:addrEnsembles.html.twig', array('formEnsemble' => $formEnsemble->createView() ));
                 }

}

UPDATE QUESTION FOR SOLUTION

thanks to the answer and the comments of Abdallah Arffak

In fact I change the relation between my 2 entites. Indeed the upload method have to be in Documentsensemble.php.

This is the code for Ensembles.php :

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

Now the code for Documentsensembles.php with upload method (callbacks etc...):

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->path ? null : $this->getUploadDir().'/'.$this->path;
        }

        protected function getUploadRootDir()
        {
            // le chemin absolu du répertoire où les documents uploadés doivent être sauvegardés
            return __DIR__.'/../../../../MySpace/'.$this->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->file) {
                $this->path = $this->file->guessExtension();
            }
        }

        /**
         * @ORM\PostPersist()
         * @ORM\PostUpdate()
         */
        public function upload()
        {
            if (null === $this->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->file->move($this->getUploadRootDir(), $this->nom.'.'.$this->file->guessExtension());

            unset($this->file);
        }

        /**
         * @ORM\PreRemove()
         */
        public function storeFilenameForRemove()
        {
            $this->filenameForRemove = $this->getAbsolutePath();
        }

        /**
         * @ORM\PostRemove()
         */
        public function removeUpload()
        {
            if ($this->filenameForRemove) {
                unlink($this->filenameForRemove);
            }
        }

        public function getAbsolutePath()
        {
            return null === $this->path ? null : $this->getUploadRootDir().'/'.$this->nom.'.'.$this->path = $this->file->guessExtension();
        }
        // The getters and the setters

and now the code for controller:

public function uploadAction() {

        $message = "Infos: aucun documents uploadé présent pour le moment";
        $em=$this->getDoctrine()->getManager();
        $documentsensemble = $em->getRepository('MySpaceDatabaseBundle:Documentsensemble');

        $documentsensemble = new Documentsensemble();
        $formUpload = $this->createForm(new DocumentsensembleType(), $documentsensemble);


        $requestUpload = $this->getRequest();

        //instruction if à plusieurs conditions: ici si la method est POST et si le formulaire est valide
        if ($requestUpload->isMethod('POST') | ($formUpload->isValid())) {

                $formUpload->bind($requestUpload);
                $documentsensemble = $formUpload->getData();
                //$documentsensemble->upload();
                //Cette ligtne est commenté car nous utilisons les callbacks pour la méthode Upload de Symfony

                $em->persist($documentsensemble);
                $em->flush();

                return $this->redirect($this->generateUrl('MySpace_formulaire_recherche_ensembles'));
            }

        //retourner le formulaire d'ajout si c'est invalide
        else {
                return $this->render('MySpaceGestionPatrimoinesBundle:Ensembles:documentsensemble.html.twig', array('formUpload' => $formUpload->createView(), 'message' => $message ));
             }

    }

Finally, I call the form in a twig in another form, there are so many methods and ways to do this, check the symfony cookbook or here for example like Abdallah Arffak suggests me.

Thank you a lot and sorry if my english is bad.

you should use this

{{ form_label(formEnsemble.file, "Transférer un fichier appartenant à cet ensemble:", {'label_attr': {'class': 'control-label'}}) }}
        <div>
         {{ form_widget(formEnsemble.file) }}
        </div>
      </div>

instead of this

{{ form_label(formEnsemble.documentsensemble, "Transférer un fichier appartenant à cet ensemble:", {'label_attr': {'class': 'control-label'}}) }}
        <div>
         {{ form_widget(formEnsemble.documentsensemble) }}
        </div>
      </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM