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.