Symfony2 + SonataAdmin + VichUploaderBundle - Image Upload Field

2.5k views Asked by At

Spent last days trying, as a newcomer to Symfony find a good solution on integrating a image upload field in an existing Entity in Sonata Admin. I've been Googling and following guides available but unfortunately I cannot figure it out.

Setup as specified in headline

Symfony2 SonataAdmin VichUploaderBundle

Im currently stuck with the following error:

"Catchable Fatal Error: Argument 1 passed to Beautify\BeautiesBundle\Entity\Beauty::setImageFile() must be an instance of Symfony\Component\HttpFoundation\File\UploadedFile, instance of Symfony\Component\HttpFoundation\File\File given, called in /Users/gmf/symfony/vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php on line 438 and defined in /Users/gmf/symfony/src/Beautify/BeautiesBundle/Entity/Beauty.php line 75 "

The image upload field renders correctly and I receive the error after submitting.

This is line 75:

/**
* If manually uploading a file (i.e. not using Symfony Form) ensure an instance
* of 'UploadedFile' is injected into this setter to trigger the  update. If this
* bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
* must be able to accept an instance of 'File' as the bundle will inject one here
* during Doctrine hydration.
*
* @param File|\Symfony\Component\HttpFoundation\File\UploadedFile
*/
public function setImageFile(UploadedFile $image = null)
{
    $this->imageFile = $image;

    if ($image) {
        // It is required that at least one field changes if you are using doctrine
        // otherwise the event listeners won't be called and the file is lost
        $this->updatedAt = new \DateTime('now');
    }
}

Hers's my other closely related files:

ENTITY FILE:

 <?php

    // src/Beautify/BeautiesBundle/Entity/Beauty.php

    namespace Beautify\BeautiesBundle\Entity;

    use Doctrine\ORM\Mapping as ORM;
    use Symfony\Component\HttpFoundation\File\UploadedFile;
    use Vich\UploaderBundle\Mapping\Annotation as Vich;

    /** 
    * @ORM\Entity
    * @ORM\Table(name="beauties")
    * @ORM\HasLifecycleCallbacks
    * @Vich\Uploadable
    */

    class Beauty
    {

        /**
        * @ORM\Column(type="integer")
        * @ORM\Id
        * @ORM\GeneratedValue(strategy="AUTO")
        */
        protected $id;

        /**
        * @ORM\Column(type="string", length=100)
        */

        protected $name;

        /**
        * @ORM\Column(type="text")
        */

        protected $content;  



        /**
        * @Vich\UploadableField(mapping="beauty_image", fileNameProperty="imageName")
        * @var File $imageFile
        */
        protected $imageFile;

        /**
        * @ORM\Column(type="string", length=255, nullable=true, name="image_name")
        * @var string $imageName
        */
        protected $imageName;



        /**
        * @ORM\ManyToOne(targetEntity="Category", inversedBy="beauties")
        * @ORM\JoinColumn(name="category_id", referencedColumnName="id")
        */
        protected $category;





        /**
        * If manually uploading a file (i.e. not using Symfony Form) ensure an instance
        * of 'UploadedFile' is injected into this setter to trigger the  update. If this
        * bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
        * must be able to accept an instance of 'File' as the bundle will inject one here
        * during Doctrine hydration.
        *
        * @param File|\Symfony\Component\HttpFoundation\File\UploadedFile
        */
        public function setImageFile(File $image = null)
        {
            $this->imageFile = $image;

            if ($image) {
                // It is required that at least one field changes if you are using doctrine
                // otherwise the event listeners won't be called and the file is lost
                $this->updatedAt = new \DateTime('now');
            }
        }

        /**
        * @return File
        */
        public function getImageFile()
        {
            return $this->imageFile;
        }

        /**
        * @param string $imageName
        */
        public function setImageName($imageName)
        {
            $this->imageName = $imageName;
        }

        /**
        * @return string
        */
        public function getImageName()
        {
            return $this->imageName;
        }






        public function __toString()
        {
            return ($this->getName()) ? : '';
        }

        /**
        * Get id
        *
        * @return integer 
        */
        public function getId()
        {
            return $this->id;
        }

        /**
        * Set name
        *
        * @param string $name
        * @return Beauty
        */
        public function setName($name)
        {
            $this->name = $name;

            return $this;
        }

        /**
        * Get name
        *
        * @return string 
        */
        public function getName()
        {
            return $this->name;
        }

        /**
        * Set content
        *
        * @param string $content
        * @return Beauty
        */
        public function setContent($content)
        {
            $this->content = $content;

            return $this;
        }

        /**
        * Get content
        *
        * @return string 
        */
        public function getContent()
        {
            return $this->content;
        }

        /**
        * Set category
        *
        * @param \Beautify\BeautiesBundle\Entity\Category $category
        * @return Beauty
        */
        public function setCategory(\Beautify\BeautiesBundle\Entity\Category $category = null)
        {
            $this->category = $category;

            return $this;
        }

        /**
        * Get category
        *
        * @return \Beautify\BeautiesBundle\Entity\Category 
        */
        public function getCategory()
        {
            return $this->category;
        }








    }

#ADMIN FILE

<?php
// src/Beautify/BeautiesBundle/Admin/BeautyAdmin.php

namespace Beautify\BeautiesBundle\Admin;

use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;

use Knp\Menu\ItemInterface as MenuItemInterface;

use Beautify\CategoryBundle\Entity\Category;


class BeautyAdmin extends Admin
{
    // Fields to be shown on create/edit forms
    protected function configureFormFields(FormMapper $formMapper)
    {
        $formMapper
        ->with('General')
        ->add('name', 'text', array('label' => 'Name'))
        ->add('content', 'textarea', array('label' => 'Content'))
        ->add('imageFile', 'file', array('label' => 'Image file', 'required' => false))
        ->end()
        ->with('Category')
        ->add('category', 'sonata_type_model', array('expanded' => true))
        ->end()
        ;
    }



    // Fields to be shown on filter forms
    protected function configureDatagridFilters(DatagridMapper $datagridMapper)
    {
        $datagridMapper
        ->add('name')
        ->add('content')
        ->add('category')
        ;
    }

    // Fields to be shown on lists
    protected function configureListFields(ListMapper $listMapper)
    {
        $listMapper
        ->addIdentifier('name')
        ->add('content')
        ->add('category')
        ->add('_action', 'actions', array(
        'actions' => array(
        'show' => array(),
        'edit' => array(),
        'delete' => array(),
        )
        ))
        ;
    }
}





**#SERVICES FILE**



report.listener:
class: Beautify\BeautiesBundle\Entity\Beauty
tags:
- { name: doctrine.event_listener, event: prePersist }
- { name: doctrine.event_listener, event: preUpdate }




    **#CONFIG.YML** 

    # Your other blocks
    vich_uploader:
    db_driver: orm

    mappings:
    beauty_image:
    uri_prefix:         /images/beauties
    upload_destination: %kernel.root_dir%/../images

Any help is very appreciated and will make me very happy

2

There are 2 answers

0
K-Phoen On

You missed the use statement for the File class: use Symfony\Component\HttpFoundation\File\File;

0
gvf On

Add the use statement above and then change the method signature to this:

public function setImageFile(File $image = null)