4

I've been trying 4 times with no luck before post this issue.

I read the documentation carefully and after installing VichUploaderBundle I created my code to upload a song as follow:

Entity/Model

namespace AppBundle\Entity;

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

/**
 * @ORM\Entity
 * @Vich\Uploadable
 */
class Song
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    // ..... other fields

    /**
     * NOTE: This is not a mapped field of entity metadata, just a simple property.
     * 
     * @Vich\UploadableField(mapping="song_track", fileNameProperty="trackName")
     * 
     * @var File
     */
    private $trackFile;

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

    /**
     * @ORM\Column(type="datetime")
     *
     * @var \DateTime
     */
    private $updatedAt;

    /**
     * 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 $trackName
     */
    public function setTrackFile(File $trackName = null)
    { 
        $this->$trackName = $trackName;
        if ($trackName) {
          var_dump($trackName);
            // 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 getTrackFile()
    {
        return $this->trackFile;
    }

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

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

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

    /**
     * Set updatedAt
     *
     * @param \DateTime $updatedAt
     *
     * @return Track
     */
    public function setUpdatedAt($updatedAt)
    {
        $this->updatedAt = $updatedAt;

        return $this;
    }

    /**
     * Get updatedAt
     *
     * @return \DateTime
     */
    public function getUpdatedAt()
    {
        return $this->updatedAt;
    }
}

Controller

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use AppBundle\Entity\Song;

class UploadTrackController extends Controller
{
    /**
     * @Route("/uploadtrack", name="uploadtrackform")
     */
    public function indexAction(Request $request)
    {
      $track = new Song();
      $form = $this->createFormBuilder($track)
          ->add('trackFile', 'file')
          ->add('save', 'submit', array('label' => 'Upload File'))
          ->getForm();
        $form->handleRequest($request);

        return $this->render('default/uploadtrack.html.twig', 
          array(
            'form' => $form->createView(),
          )
        );
    }
}

View

<body>
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
</body>

I can see the form, upload a file and the controller is triggered correctly. I don't get any errors but neither the file is copied in the folder or the data persisted to the database.

You can see in my Entity I have a var_dump which is actually containing an error property. Once the form has been submitted this is what I get from that var_dump:

object(Symfony\Component\HttpFoundation\File\UploadedFile)#13 (7) { ["test":"Symfony\Component\HttpFoundation\File\UploadedFile":private]=> bool(false) ["originalName":"Symfony\Component\HttpFoundation\File\UploadedFile":private]=> string(24) "file.pdf" ["mimeType":"Symfony\Component\HttpFoundation\File\UploadedFile":private]=> string(15) "application/pdf" ["size":"Symfony\Component\HttpFoundation\File\UploadedFile":private]=> int(186992) ["error":"Symfony\Component\HttpFoundation\File\UploadedFile":private]=> int(0) ["pathName":"SplFileInfo":private]=> string(66) "/private/var/folders/1g/4t5n9rhj0_s_9tnstpjj6w_w5wl8pn/T/phpptwjZH" ["fileName":"SplFileInfo":private]=> string(9) "phpptwjZH" }

It seems to me that the file is stored temporally somewhere but never copied in the folder and therefore no data is persisted to the db by doctrine.

Sorry if I didn't find a way to be more concise, but this question is mainly for those who have experience with Symfony and VichUploaderBundle.

Thank you in advance

Just in case you were wondering what are the config for the bundle, here we go:

#VichUpload config
vich_uploader:
    db_driver: orm # or mongodb or propel or phpcr
    mappings:
        song_track:
            uri_prefix:         /upload/tracks
            upload_destination: %kernel.root_dir%/../web/upload/tracks

UPDATE

modified setter in the Song entity like K-Phoen suggested below, still same issue :/ PS: I'm running the project using the Symfony internal server php app/console server:run

public function setTrackFile(File $trackFile = null)
{
    $this->trackFile = $trackFile;
    if($trackFile){
      var_dump($trackFile);
        // 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');
    }
}

UPDATE 2

Adding this to my controller made the whole thing working, files are copied, database is written ...

 if ($form->isValid()) {
    $em = $this->getDoctrine()->getManager();
    $em->persist($track);
    $em->flush();
}

...By the way, I'm confused at this point since reading the VichUploaderBundle documentation I understood this persisting was called automatically without need to specify anything else then $form->handleRequest($request); in the controller.

Meeku
  • 53
  • 2
  • 7

1 Answers1

0

The setTrackFile(…) setter is incorrect: it should update the trackFile attribute instead of trackName.

public function setTrackFile(File $trackFile = null)
{
    $this->trackFile = $trackFile;

    // …
}
K-Phoen
  • 1,260
  • 9
  • 18
  • Thank you (also for the bundle, indeed), I tried with your setTrack method still the file is not copied and nothing is persisted to the database :/, not getting any errors though, even in the symfony console can't spot anything the only error I see is in the var_dump output (again), ["error":"Symfony\Component\HttpFoundation\File\UploadedFile":private]=> int(1) – Meeku Oct 29 '15 at 22:33