I have read questions concerning this topic and also seen responses that have been of importance thus far, but am currently experiencing some programming difficulties related to this same issue. I am trying to upload multiple files using the Symfony 3 framework and it's been a challenge really. I have the following code for doing this;
The first is the Form Type am using:
class ProductImageType extends AbstractType
{
/**
* Build the form
* #param None
* #return void
**/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('file', FileType::class, array('attr'=>array('class'=>'form-control'), 'multiple' => true));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(
array(
'data_class' => 'AppBundle\Entity\ProductImages',
)
);
}
public function getName()
{
return 'ProductImageType';
}
}
This is the Entity Am using:
class ProductImages
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="productSku", type="string", length=15, unique=true)
*/
private $productSku;
/**
* #var string $file
*
* #ORM\Column(name="file", type="string", length=255)
* #Assert\NotBlank(message="You must select at least one valid image file.")
*
*/
private $file;
/**
* #var int
*
* #ORM\Column(name="dateCreated", type="integer", nullable=true)
*/
private $dateCreated;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set productSku
*
* #param string $productSku
*
* #return productImages
*/
public function setProductSku($productSku)
{
$this->productSku = $productSku;
return $this;
}
/**
* Get productSku
*
* #return string
*/
public function getProductSku()
{
return $this->productSku;
}
/**
* Set images
*
* #param UploadedFile $file
*
* #return productImages
*/
public function setFile($file = null)
{
$this->file = $file;
return $this;
}
/**
* Get images
*
* #return string
*/
public function getFile()
{
return $this->file;
}
/**
* Set dateCreated
*
* #param integer $dateCreated
*
* #return productImages
*/
public function setDateCreated($dateCreated)
{
$this->dateCreated = $dateCreated;
return $this;
}
/**
* Get dateCreated
*
* #return int
*/
public function getDateCreated()
{
return $this->dateCreated;
}
}
And this is the controller am using to handle the file upload:
public function uploadAction(Request $request)
{
$files = $request->files->get('product_image');
$sku = $request->request->get('productSku');
$uploaded = false;
$message = null;
$count = 0;
$image_files = [];
$uploadDir = $this->getParameter('products_images_directory') . DIRECTORY_SEPARATOR . $sku . DIRECTORY_SEPARATOR;
$mimeTypes = array('image/jpeg','image/jpg','image/png','image/gif','image/bmp');
$doctrine = $this->getDoctrine()->getManager();
if(!empty($files))
{
foreach($files as $file => $v)
{
$filename[$count] = $sku . '_' . $count . '.' . $v[$count]->guessExtension();
$image_files[$count]['file'] = $filename[$count];
$image_files[$count]['file_size'] = $v[$count]->getClientSize();
Dump($image_files);die;
/**if(!is_dir($uploadDir) && !file_exists($uploadDir . $filename))
{
mkdir($uploadDir, 0775, TRUE);
if($value[$count]->move($uploadDir, $filename))
{
$productImages = new ProductImages();
$productImages->setProductSku($sku);
$productImages->setFile($filename[$i]);
$productImages->setDateCreated(strtotime(date('y-m-d h:i:s a')));
$doctrine->persist($productImages);
$doctrine->flush();
}
}
**/
$count++;
}
Dump($image_files);die('Action ended!');
if($count>1)
{
$uploaded = TRUE;
$message = "All Images have been uploaded & saved!!";
}
}
Dump($message);die;
return (new JsonResponse(
[
'uploaded'=>$uploaded,
'message'=>$message
]
));
}
I was going to use Dropzone.js to handle the front-end, i had to make sure everything works fine before integrating it. I discovered that when I try uploading multiple images using the foreach(...) only one of the images gets uploaded. on Dump(...) of the content of $request->request->get(...) i see the multiple files that were selected, but the foreach(...) only fetches the content of the first array not the second or third... I know the problem is within this condition, but i can't figure it out. Does someone have the sixth eye to assist, please?????
After much sleepless hours, i was able to finally get Symfony to work with dropzone.js for multiple (image) file uploads. This might be tweaked to work with other types of files of course:
My Entity:
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* productImages
*
* #ORM\Table(name="product_images")
* #ORM\Entity(repositoryClass="AppBundle\Repository\productImagesRepository")
*/
class ProductImages
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="productSku", type="string", length=15, unique=true)
*/
private $productSku;
/**
*
* #ORM\Column(name="files", type="string", length=255)
* #Assert\NotBlank(message="You must select at least one valid image
file.")
*
*/
private $files;
/**
* #var int
*
* #ORM\Column(name="dateCreated", type="integer", nullable=true)
*/
private $dateCreated;
/**
* Class Contructor
*
* #param array $options
* #return void
*/
public function __construct()
{}
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set productSku
*
* #param string $productSku
*
* #return productImages
*/
public function setProductSku($productSku = NULL)
{
$this->productSku = $productSku;
return $this;
}
/**
* Get productSku
*
* #return string
*/
public function getProductSku()
{
return $this->productSku;
}
/**
* Set image Files
*
* #param String $files
*
* #return productImages
*/
public function setFiles($files = NULL)
{
$this->files = (string)$files;
return $this;
}
/**
* Get image Files
*
* #return string
*/
public function getFiles()
{
return $this->files;
}
/**
* Set dateCreated
*
* #param integer $dateCreated
*
* #return productImages
*/
public function setDateCreated($dateCreated)
{
$this->dateCreated = $dateCreated;
return $this;
}
/**
* Get dateCreated
*
* #return int
*/
public function getDateCreated()
{
return $this->dateCreated;
}
}
Form Type:
class ProductImageType extends AbstractType
{
/**
* Build the form
* #param None
* #return void
**/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('files', FileType::class, array('attr'=>array('class'=>'form-control'), 'multiple' => true));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(
array(
'data_class' => 'AppBundle\Entity\ProductImages',
)
);
}
public function getName()
{
return 'ProductImageType';
}
}
Controller Action:
/**
* Upload Product Image(s)
*
* #Route("/admin/products/upload", name="uploadProductImageRoute")
*
* #access public
* #param Request $request
* #return Object
**/
public function uploadInitAction(Request $request)
{
$files = $request->files->get('files');
$sku = $request->request->get('productSku');
$uploaded = false;
$message = null;
$count = $countValid = 0 ;
$mimeTypes = array('jpeg','jpg','png','gif','bmp');
if(!empty($files))
{
for($count; $count < count($files); $count++)
{
if(in_array($files[$count]->guessClientExtension(), $mimeTypes))
$countValid++;
}
if($countValid == count($files))
$uploaded = $this->uploadExec($sku, $files);
}
if($uploaded)
$message = "All Images have been uploaded & saved!!";
else
$message = "Selected File(s) weren't uploaded!!";
return $this->json(
[
'uploaded' => $uploaded,
'message' => $message
]
);
}
/**
* Performs Actual File Upload
*
* #param string $sku
* #param array $args
* #return Boolean
*
*/
private function uploadExec($sku, $args = array())
{
/**
* Make sure this is a new product without images saved yet
*/
if($this->hasImages($sku))return FALSE;
$count = 0;
$image_files = [];
$doctrine = $this->getDoctrine()->getManager();
$uploadDir = $this->getParameter('products_images_directory') . DIRECTORY_SEPARATOR . $sku . DIRECTORY_SEPARATOR;
if(!is_dir($uploadDir))
{
mkdir($uploadDir, 0775, TRUE);
}
if(!empty($args) && count($args) > 0)
{
for($count; $count < count($args); $count++)
{
$filename[$count] = $sku . '_' . $count . '.' . $args[$count]->guessClientExtension();
if(!file_exists($uploadDir . $filename[$count]))
{
if($args[$count]->move($uploadDir, $filename[$count]))
{
$image_files[$count]['file'] = $filename[$count];
$image_files[$count]['file_size'] = $args[$count]->getClientSize();
//$image_files[$count]['file_location'] = $uploadDir;
}
}
}
$jsonEncodeFiles = json_encode($image_files);
/*
* Persist Uploaded Image(s) to the Database
*/
$productImages = new ProductImages();
$productImages->setProductSku($sku);
$productImages->setFiles($jsonEncodeFiles);
$productImages->setDateCreated(strtotime(date('y-m-d h:i:s a')));
$doctrine->persist($productImages);
$doctrine->flush();
if( NULL != $productImages->getId() )return TRUE;
}
return FALSE;
}
Template:
{{ form_start(uploadForm, {'action':path('uploadProductImageRoute'), 'method' : 'POST', 'attr': {'id' : 'form-with-dropzone', 'class' : 'form-horizontal dropzone' }}) }}
<input type="hidden" name="productSku" value="{{ sku }}" />
<div class="row">
<div class="dropzone-previews"></div>
<div class="fallback">
{{ form_widget(uploadForm.files) }}
</div>
</div>
{{ form_end(uploadForm) }}
<div class="row no-margin-right no-margin-left">
<div class="form-group no-margin-right no-margin-left" style="margin-top: 30px;">
<div class="pull-right">
<button id="submit" type="submit" class="btn btn-sm btn-inverse"><i class="ace-icon typcn typcn-location-arrow-outline align-top bigger-115"></i> Upload Image(s)</button>
</div>
</div>
</div>
Javascript:
Dropzone.options.formWithDropzone = {
autoProcessQueue: false,
uploadMultiple: true,
paramName: "files",
parallelUploads: 10,
maxFiles: 10,
addRemoveLinks: true,
acceptedFiles: 'image/*',
init: function(){
var dropZone = this;
$('#submit').click(function(e){
e.preventDefault();
e.stopPropagation();
dropZone.processQueue();
});
dropZone.on("success", function(file, response) {
if(dropZone.getAcceptedFiles().length > 0){
$.gritter.add({
title : 'Upload Complete',
text : response.message + '\n\nA total of: ' + dropZone.getAcceptedFiles().length + ' images uploaded successfully!',
class_name : 'gritter-success'
})
}else{
$.gritter.add({
title : 'Upload Incomplete',
text : response.message,
class_name : 'gritter-error'
})
}
});
}
}
There was no need of making complex and unnecessary entity relationship mappings to get this to do what i wanted it to.
While working on this, i realized that using the getMimeType() method of the UploadedFile class to check the mimetype of the uploaded files(s) resulted in the error:
FileNotFoundException in MimeTypeGuesser.php line 123:
The file "F:\wamp2.5\tmp\php....tmp" does not exist
However, the error disappeard after i changed the method getMimeType() to guessClientExtension()
In future, i hope this will save someone a lot of time.
Related
I am new to PHP. I succeeded in uploading single image to a form and saving it in the database. But when I modify that to upload multiple images, I get an error saying
The form's view data is expected to be an instance of class Symfony\Component\HttpFoundation\File\File, but is a(n) array.
class SatelliteImages
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var array
*/
private $files= array();
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
*Set files
*
* #param UploadedFile[] $files
*/
public function setFiles($files)
{
$this->files = $files;
//return $this;
}
/**
* Get files
*
* #return UploadedFile[]
*/
public function getFiles()
{
return $this->files;
}
/**
* #param satelliteImage[] $images
*
* #return satelliteImage[]
*
*/
public function upload($images){
foreach ($this->getFiles() as $key => $file) {
$images[$key]->setImage(file_get_contents($file));
}
return $images;
}
}
This is the SatelliteImage entity(single image)
class satelliteImage
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var float
*
* #ORM\Column(name="latitude", type="float")
*/
private $latitude;
/**
* #var float
*
* #ORM\Column(name="longitude", type="float")
*/
private $longitude;
/**
* #var string
*
* #ORM\Column(name="image", type="blob", nullable=true))
*/
private $image;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
public $path;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set latitude
*
* #param float $latitude
*
* #return satelliteImage
*/
public function setLatitude($latitude)
{
$this->latitude = $latitude;
return $this;
}
/**
* Get latitude
*
* #return float
*/
public function getLatitude()
{
return $this->latitude;
}
/**
* Set longitude
*
* #param float $longitude
*
* #return satelliteImage
*/
public function setLongitude($longitude)
{
$this->longitude = $longitude;
return $this;
}
/**
* Get longitude
*
* #return float
*/
public function getLongitude()
{
return $this->longitude;
}
/**
* Set image
*
* #param string $image
*
* #return satelliteImage
*/
public function setImage($image)
{
$this->image = $image;
return $this;
}
/**
* Get image
*
* #return string
*/
public function getImage()
{
return $this->image;
}
/**
* Get path
*
* #return string
*/
public function getPath()
{
return $this->path;
}
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()
{
// the absolute directory path where uploaded
// documents should be saved
return __DIR__.'/../../../../web/'.$this->getUploadDir();
}
protected function getUploadDir()
{
// get rid of the __DIR__ so it doesn't screw up
// when displaying uploaded doc/image in the view.
return 'uploads/documents';
}
/**
* #Assert\File(maxSize="6000000")
*/
private $file;
/**
* Sets file.
*
* #param UploadedFile $file
*/
public function setFile(UploadedFile $file = null)
{
$this->file = $file;
}
/**
* Get file.
*
* #return UploadedFile
*/
public function getFile()
{
return $this->file;
}
public function upload()
{
// the file property can be empty if the field is not required
if (null === $this->getFile()) {
return;
}
$imgFile=$this->getFile();
$this->setImage(file_get_contents($imgFile));
// clean up the file property as you won't need it anymore
$this->file = null;
}
}
In my controller, how can I create an array of images and pass it to the above function?
/**
* #Route("/uploads", name="upload_images")
*
*/
public function uploadImages(Request $request)
{
$images=new Images();
$form = $this->createForm(ImageFile::class, $images);
$form->handleRequest($request);
$em=$this->getDoctrine()->getManager();
$images->upload(????);
}
ImageFile class:
class ImageFile extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('files', FileType::class, array(
'attr' => array(
'accept' => 'image/*',
'multiple' => 'multiple'
)
))
->add('save',SubmitType::class,array('label'=>'Insert Image','attr'=>array('class'=>'btn btn-primary','style'=>'margin-bottom:15px')))
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => SatelliteImages::class
));
}
}
This code right here is a problem:
/**
* #Assert\File(maxSize="60000000")
*/
private $files= array();
You need to fix that. You are asserting it's a file, but then you specify that it's an array!
EDIT #2
Your upload function has a problem too. You are returning the same parameter that you are passing in ($images). So you need to change it like so:
/**
* #param satelliteImage[] $images
*
* #return satelliteImage[]
*
*/
public function upload($images){
foreach ($this->getFiles() as $key => $file) {
$img[$key]->setImage(file_get_contents($file));
}
return $img;
}
EDIT #3
The buildForm function seems ok. In your Controller, I think you need to create the class and load the form like this:
$images = new SatelliteImages();
$form = $this->createFormBuilder($images);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$images = $form->getData();
$em = $this->getDoctrine()->getManager();
$em->persist($images);
$em->flush();
return $this->redirectToRoute('some_path');
}
Can you try it? Not sure if that's the problem or not.
SOLUTION
I managed to resolve previous issue by changing 'FileType' to 'CollectionType' in imageFile class's buildForm() function
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('files', CollectionType::class, array(
'attr' => array(
'accept' => 'image/*',
'multiple' => 'multiple'
)
))
->add('save',SubmitType::class,array('label'=>'Insert Image','attr'=>array('class'=>'btn btn-primary','style'=>'margin-bottom:15px')))
;
}
I also changed the 'files' like this
/**
* #var array
*/
private $files;
public function __construct()
{
$this->files = new ArrayCollection();
}
However, when I do that, the 'browse images' button disappears from the view. Any suggestions to fix that?
I also tried removing the construct() function. When I do that, it gives me an error in the controller saying "invalid argument supplied for foreach"
I have some issues with the update of an entity with a file field on it. I don't know what it can be, because I did that a lot of time, but today it won't work.
So this is the entity:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Consigli
*
* #ORM\Table()
* #ORM\HasLifecycleCallbacks
* #ORM\Entity(repositoryClass="AppBundle\Entity\Repository\ConsigliRepository")
*/
class Consigli
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="titolo", type="string", length=255)
*/
private $titolo;
/**
* #var string
*
* #ORM\Column(name="testo", type="text")
*/
private $testo;
/**
* #var string $image
* #Assert\File( maxSize = "60000000", mimeTypesMessage = "Perfavore inserisci un'immagine valida!")
* #ORM\Column(name="image", type="string", length=255, nullable=true)
*/
private $image;
/**
* #ORM\ManyToOne(targetEntity="Categoria", inversedBy="categoria")
* #ORM\JoinColumn(name="categoria_id", referencedColumnName="id")
*/
protected $categoria;
/**
* #var date
*
* #ORM\Column(name="data", type="date")
*/
public $data;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set titolo
*
* #param string $titolo
*
* #return Consigli
*/
public function setTitolo($titolo)
{
$this->titolo = $titolo;
return $this;
}
/**
* Get titolo
*
* #return string
*/
public function getTitolo()
{
return $this->titolo;
}
/**
* Set testo
*
* #param string $testo
*
* #return Consigli
*/
public function setTesto($testo)
{
$this->testo = $testo;
return $this;
}
/**
* Get testo
*
* #return string
*/
public function getTesto()
{
return $this->testo;
}
/**
* Set image
*
* #param string $image
*/
public function setImage($image)
{
$this->image = $image;
}
/**
* Get image
*
* #return string
*/
public function getImage()
{
return $this->image;
}
public function getFullImagePath() {
return null === $this->image ? null : $this->getUploadRootDir(). $this->image;
}
protected function getUploadRootDir() {
// the absolute directory path where uploaded documents should be saved
return $this->getTmpUploadRootDir().$this->getId()."/";
}
protected function getTmpUploadRootDir() {
// the absolute directory path where uploaded documents should be saved
return __DIR__ . '/../../../web/immaginiConsigli/';
}
/**
* #ORM\PrePersist()
* #ORM\PreUpdate()
*/
public function uploadImage() {
// the file property can be empty if the field is not required
if (null === $this->image) {
return;
}
if(!$this->id){
$this->image->move($this->getTmpUploadRootDir(), $this->image->getClientOriginalName());
}else{
return null;
}
$this->setImage($this->image->getClientOriginalName());
}
/**
* #ORM\PostPersist()
*/
public function moveImage()
{
if (null === $this->image)
{
return;
}
if (!is_dir($this->getUploadRootDir()))
{
mkdir($this->getUploadRootDir());
}
copy($this->getTmpUploadRootDir() . $this->image, $this->getFullImagePath());
unlink($this->getTmpUploadRootDir() . $this->image);
}
/**
* Set data
*
* #param \DateTime $data
*
* #return Consigli
*/
public function setData($data)
{
$this->data = $data;
return $this;
}
/**
* Get data
*
* #return \DateTime
*/
public function getData()
{
return $this->data;
}
/**
* Set categoria
*
* #param \AppBundle\Entity\Categoria $categoria
*
* #return Consigli
*/
public function setCategoria(\AppBundle\Entity\Categoria $categoria = null)
{
$this->categoria = $categoria;
return $this;
}
/**
* Get categoria
*
* #return \AppBundle\Entity\Categoria
*/
public function getCategoria()
{
return $this->categoria;
}
}
The file is stored in a folder, that is as you can see "immaginiConsigli", and in the table of the database I have the "image" field, that stores the name of the image.
The update action in the controller is:
public function modificaconsiglioAction(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$consiglio = $em->getRepository('AppBundle:Consigli')->find($id);
$form = $this->createForm(new ConsiglioType($consiglio), $consiglio);
$form->handleRequest($request);
if ($form->isValid())
{
$em = $this->getDoctrine()->getManager();
try
{
$em->persist($consiglio);
$em->flush();
return $this->redirect($this->generateUrl('successconsigliomodificato'));
} catch (\Exception $e)
{
$form->addError(new FormError('errore nel database: ' . $e->getMessage()));
}
if ($form->isValid())
{
$var = $consiglio;
$em->persit($var);
$em->flush();
return $this->redirect($this->generateUrl('successconsigliomodificato'));
} else
{
}
}
return $this->render('adminarea/modificaconsiglio.html.twig', array(
'consiglio' => $consiglio,
'form' => $form->createView()));
}
So what happens is: I want to update an already existing record, that of course has already the file in it. The update seems to work, but when I render the new and updated record, the image doesn't show, and in the database I always get something like this:
/tmp/php1QyeYr
That is not the name of the image.
And also, the new file/image, it isn't inserted in the folder.
So, anyone knows what I'm doing wrong?
after looking again, I think I see the problem.
Your query will return an array of matched entities, not the match itself. You need to call findOneBy instead.
public function modificaconsiglioAction( Request $request, $id ) {
$em = $this->getDoctrine()
->getManager();
$consiglio = $em->getRepository( 'AppBundle:Consigli' )
->findOneBy( [ 'id' => $id ] );
if ( null !== $consiglio ) {
$form = $this->createForm( new ConsiglioType( $consiglio ), $consiglio );
$form->handleRequest( $request );
if ( $form->isSubmitted() && $form->isValid() ) {
$em->persist( $consiglio );
$em->flush();
return $this->redirect( $this->generateUrl( 'successconsigliomodificato' ) );
}
} else {
// do something about letting the user know the id matched nothing
}
return $this->render( 'adminarea/modificaconsiglio.html.twig', [
'consiglio' => $consiglio,
'form' => $form->createView(),
] );
}
Its also worth noting that you can get away without making your own query to the database. If you change your method signature to:
public function modificaconsiglioAction( Request $request, Consigli $consigli ) {
Symfony will automatically query the database for you based on the $id sent to the controller in the route.
Because I have a custom built jQuery plugin to pass file uploads to my symfony2 webapp I am looking for ways to handle this upload in the controller.
The standard (non-ajax) file upload that I currently have (and that works fine for synchronous calls) looks like this
Controller excerpt
...
$entity = new Image();
$request = $this->getRequest();
$form = $this->createForm(new ImageType($createAction), $entity);
$form->bind($request); // <-- Find a way to make this connection manually?!
//check that a file was chosen
$fileExists = isset($entity->file);
if ( ($form->isValid()) && ($fileExists) ) {
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
}
...
Form Type: The form just takes the file and a name:
class ImageType extends AbstractType
{
...
public function buildForm(FormBuilderInterface $builder, array $options)
{
$createAction = $this->createAction;
if ($createAction) {
$builder
->add('file')
;
}
$builder
->add('name', 'text', array('label' => 'Namn'))
;
}
...
}
As I understand (or in other words DON'T apparently understand) the file upload system with symfony2 and doctrine there is quite a bit of magic going on underneath the hood on this call
$form->bind($request);
For example, if I skip this bind() and instead try to create the Image entity manually like this...
$request = $this->getRequest();
$parent = $request->request->get('parent');
$file = $request->request->get('file1');
$name = $request->request->get('name');
$entity->setName( $name );
$entity->setFile( $file );
$entity->setFolder( null );
... I find that it doesn't even have a setFile() so that is taken care of in some other way. Here is that Image entity:
namespace BizTV\MediaManagementBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* BizTV\MediaManagementBundle\Entity\Image
*
* #ORM\Table(name="image")
* #ORM\Entity
* #ORM\HasLifecycleCallbacks
*/
class Image
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string $name
*
* #ORM\Column(name="name", type="string", length=255)
* #Assert\NotBlank(message = "Bilden måste ha ett namn")
*/
private $name;
/**
* #var integer $width
*
* #ORM\Column(name="width", type="integer")
*/
private $width;
/**
* #var integer $height
*
* #ORM\Column(name="height", type="integer")
*/
private $height;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $path;
//The deleteRequested variable is to flag that an image has been deleted by user.
//Due to slideshow issues we can however not delete the image right away, we can't risk to remove it from the
//cache manifest before the slideshow round is up.
/**
* #var time $deleteRequested
*
* #ORM\Column(name="delete_requested", type="datetime", nullable=true)
*/
private $deleteRequested;
/**
* #var object BizTV\BackendBundle\Entity\company
*
* #ORM\ManyToOne(targetEntity="BizTV\BackendBundle\Entity\company")
* #ORM\JoinColumn(name="company", referencedColumnName="id", nullable=false)
*/
protected $company;
/**
* #var object BizTV\MediaManagementBundle\Entity\Folder
*
* #ORM\ManyToOne(targetEntity="BizTV\MediaManagementBundle\Entity\Folder")
* #ORM\JoinColumn(name="folder", referencedColumnName="id", nullable=true)
*/
protected $folder;
/**
* #Assert\File(maxSize="12000000")
*/
public $file;
/**
* #ORM\OneToOne(targetEntity="BizTV\MediaManagementBundle\Entity\QrImage", mappedBy="image")
*/
protected $qr;
/**
* #ORM\PrePersist()
* #ORM\PreUpdate()
*/
public function preUpload()
{
if (null !== $this->file) {
// do whatever you want to generate a unique name
$this->path = sha1(uniqid(mt_rand(), true)).'.'.$this->file->guessExtension();
}
}
/**
* #ORM\PostPersist()
* #ORM\PostUpdate()
*/
public function upload()
{
if (null === $this->file) {
return;
}
// if there is an error when moving the file, an exception will
// be automatically thrown by move(). This will properly prevent
// the entity from being persisted to the database on error
$this->file->move($this->getUploadRootDir(), $this->path);
unset($this->file);
}
/**
* #ORM\PostRemove()
*/
public function removeUpload()
{
if ($file = $this->getAbsolutePath()) {
unlink($file);
}
}
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()
{
// the absolute directory path where uploaded documents should be saved
return __DIR__.'/../../../../web/'.$this->getUploadDir();
}
protected function getUploadDir()
{
// get rid of the __DIR__ so it doesn't screw when displaying uploaded doc/image in the view.
return 'uploads/images/'.$this->getCompany()->getId();
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*/
public function setName($name)
{
$this->name = $name;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set width
*
* #param integer $width
*/
public function setWidth($width)
{
$this->width = $width;
}
/**
* Get width
*
* #return integer
*/
public function getWidth()
{
return $this->width;
}
/**
* Set height
*
* #param integer $height
*/
public function setHeight($height)
{
$this->height = $height;
}
/**
* Get height
*
* #return integer
*/
public function getHeight()
{
return $this->height;
}
/**
* Set path
*
* #param string $path
*/
public function setPath($path)
{
$this->path = $path;
}
/**
* Get path
*
* #return string
*/
public function getPath()
{
return $this->path;
}
/**
* Set company
*
* #param BizTV\BackendBundle\Entity\company $company
*/
public function setCompany(\BizTV\BackendBundle\Entity\company $company)
{
$this->company = $company;
}
/**
* Get company
*
* #return BizTV\BackendBundle\Entity\company
*/
public function getCompany()
{
return $this->company;
}
/**
* Set folder
*
* #param BizTV\MediaManagementBundle\Entity\Folder $folder
*/
public function setFolder(\BizTV\MediaManagementBundle\Entity\Folder $folder = NULL)
{
$this->folder = $folder;
}
/**
* Get folder
*
* #return BizTV\MediaManagementBundle\Entity\Folder
*/
public function getFolder()
{
return $this->folder;
}
/**
* Set qr
*
* #param BizTV\MediaManagementBundle\Entity\QrImage $qr
*/
public function setQr(\BizTV\MediaManagementBundle\Entity\QrImage $qr = null)
{
$this->qr = $qr;
}
/**
* Get qr
*
* #return BizTV\MediaManagementBundle\Entity\QrImage
*/
public function getQr()
{
return $this->qr;
}
/**
* Set deleteRequested
*
* #param date $deleteRequested
*/
public function setDeleteRequested($deleteRequested = null)
{
$this->deleteRequested = $deleteRequested;
}
/**
* Get deleteRequested
*
* #return date
*/
public function getDeleteRequested()
{
return $this->deleteRequested;
}
}
I found what I was looking for. To access the files uploaded to symfony from the controller, you just need to do this:
$request = $this->getRequest();
$file = $request->files->get('file1'); //file1 being the name of my form field for the file
/* if your entity is set up like mine - like they teach you in the symfony2 cookbook
* file is actually a public property so you can just set it like this
**/
$entity->file = $file;
//and here's how you get the original name of that file
$entity->setName( $file->getClientOriginalName() );
First of all, if you want to get an entity with your file after form submit/bind/handleRequest or smth else, you need to provide data_class option in form configuration method (setDefaultOptions etc.). And only after that your form will start to return needed entity after submission.
1)First of All create your entity :
namespace XXX;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Table()
* #ORM\Entity
*/
class Article
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string $image
* #Assert\File( maxSize = "1024k", mimeTypesMessage = "Please upload a valid Image")
* #ORM\Column(name="image", type="string", length=255)
*/
private $image;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set image
*
* #param string $image
*/
public function setImage($image)
{
$this->image = $image;
}
/**
* Get image
*
* #return string
*/
public function getImage()
{
return $this->image;
}
}
2) build your form: So we will then create a simple form type for this Article entity in order to fit into the other forms: ArticleType.php
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
class ArticleType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder
->add('image')
->add('...')
;
}
public function getName()
{
return 'xxx_articletype';
}
}
3)Create the controller: The controller below shows you how to manage the whole process: ArticleController.php:
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
/**
* Article controller.
*
*/
class ArticleController extends Controller
{
/**
* Finds and displays a Article entity.
*
*/
public function showAction($id)
{
$em = $this->getDoctrine()->getEntityManager();
$entity = $em->getRepository('XXXBundle:Article')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Article entity.');
}
return $this->render('XXXBundle:Article:show.html.twig', array(
'entity' => $entity,
));
}
/**
* Displays a form to create a new Article entity.
*
*/
public function newAction()
{
$entity = new Article();
//$entity = $em->getRepository('CliniqueGynecoBundle:Article');
$form = $this->createForm(new ArticleType(), $entity);
return $this->render('XXXBundle:Article:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView()
));
}
/**
* Creates a new Article entity.
*
*/
public function createAction()
{
$entity = new Article();
$request = $this->getRequest();
$form = $this->createForm(new ArticleType(), $entity);
$form->bindRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getEntityManager();
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('article_show', array('id' => $entity->getId())));
}
return $this->render('XXXBundle:Article:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView()
));
}
private function createDeleteForm($id)
{
return $this->createFormBuilder(array('id' => $id))
->add('id', 'hidden')
->getForm()
;
}
}
4) layout for the upload form: new.html.twig
<form action="{{ path('basearticle_create') }}" method="post" {{ form_enctype(form) }}>
{{ form_widget(form) }}
<p>
<button class="btn btn-primary" type="submit">Create</button>
</p>
</form>
5) Display layout: show.html.twig
<table>
<tr>
<td align="center" valign="top"><img src="{{ asset('upload/' ~ entity.id ~'/' ~ entity.image)}}" alt="" height="525" width="666" /></td>
</tr>
</table>
6) Use the « Lifecycle Callbacks » hooking the entity in a « Lifecycle callbacks »: « # ORM \ HasLifecycleCallbacks »
/**
*
* #ORM\Table()
* #ORM\HasLifecycleCallbacks
* #ORM\Entity
*/
class Article
{
....
7) Added methods to download files:
class Article
{
....................................
public function getFullImagePath() {
return null === $this->image ? null : $this->getUploadRootDir(). $this->image;
}
protected function getUploadRootDir() {
// the absolute directory path where uploaded documents should be saved
return $this->getTmpUploadRootDir().$this->getId()."/";
}
protected function getTmpUploadRootDir() {
// the absolute directory path where uploaded documents should be saved
return __DIR__ . '/../../../../web/upload/';
}
/**
* #ORM\PrePersist()
* #ORM\PreUpdate()
*/
public function uploadImage() {
// the file property can be empty if the field is not required
if (null === $this->image) {
return;
}
if(!$this->id){
$this->image->move($this->getTmpUploadRootDir(), $this->image->getClientOriginalName());
}else{
$this->image->move($this->getUploadRootDir(), $this->image->getClientOriginalName());
}
$this->setImage($this->image->getClientOriginalName());
}
/**
* #ORM\PostPersist()
*/
public function moveImage()
{
if (null === $this->image) {
return;
}
if(!is_dir($this->getUploadRootDir())){
mkdir($this->getUploadRootDir());
}
copy($this->getTmpUploadRootDir().$this->image, $this->getFullImagePath());
unlink($this->getTmpUploadRootDir().$this->image);
}
/**
* #ORM\PreRemove()
*/
public function removeImage()
{
unlink($this->getFullImagePath());
rmdir($this->getUploadRootDir());
}
I'm trying to figure out how to do multiple file uploads but without luck. I have not been able to get too much info on this.. Maybe someone here will help me out? :D
Criteria:
I know that in my form type I'm supposed to use multiples for fields; but when I add it, it gives me the this error.
Catchable Fatal Error: Argument 1 passed to
PhotoGalleryBundle\Entity\Image::setFile() must be an instance of
Symfony\Component\HttpFoundation\File\UploadedFile, array given,
called in
/home/action/workspace/www/DecorInterior/vendor/symfony/symfony/src/Symfony/Component/PropertyAccess/PropertyAccessor.php
on line 442 and defined
Image Entity
Here is my code in PHP:
<?php
namespace PhotoGalleryBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* Image
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="PhotoGalleryBundle\Entity\ImageRepository")
* #ORM\HasLifecycleCallbacks
*/
class Image
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="imageCaptation", type="string", length=255)
* #Assert\NotBlank
*/
private $imageCaptation;
/**
* #var string
*
* #ORM\Column(name="imageName", type="string", length=255)
*/
private $imageName;
/**
* #var string
*
* #ORM\Column(name="imageFilePath", type="string", length=255, nullable=true)
*/
private $imageFilePath;
/**
* #var \DateTime
*
* #ORM\Column(name="imageUploadedDate", type="datetime")
* #Gedmo\Timestampable(on="create")
*/
private $imageUploadedDate;
/**
* #Assert\File(maxSize="6000000")
*/
private $file;
/**
* #ORM\ManyToOne(targetEntity="Album", inversedBy="images")
* #ORM\JoinColumn(name="album", referencedColumnName="id")
*/
private $album;
private $temp;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set imageCaptation
*
* #param string $imageCaptation
* #return Image
*/
public function setImageCaptation($imageCaptation)
{
$this->imageCaptation = $imageCaptation;
return $this;
}
/**
* Get imageCaptation
*
* #return string
*/
public function getImageCaptation()
{
return $this->imageCaptation;
}
/**
* Set imageName
*
* #param string $imageName
* #return Image
*/
public function setImageName($imageName)
{
$this->imageName = $imageName;
return $this;
}
/**
* Get imageName
*
* #return string
*/
public function getImageName()
{
return $this->imageName;
}
/**
* Set imageFilePath
*
* #param string $imageFilePath
* #return Image
*/
public function setImageFilePath($imageFilePath)
{
$this->imageFilePath = $imageFilePath;
return $this;
}
/**
* Get imageFilePath
*
* #return string
*/
public function getImageFilePath()
{
return $this->imageFilePath;
}
/**
* Get imageUploadedDate
*
* #return \DateTime
*/
public function getImageUploadedDate()
{
return $this->imageUploadedDate;
}
/**
* Set file.
*
* #param UploadedFile $file
*/
public function setFile(UploadedFile $file = null) {
$this->file = $file;
// check if we have an old image path
if (isset($this->imageFilePath)) {
// store the old name to delete after the update
$this->temp = $this->imageFilePath;
$this->imageFilePath = null;
} else {
$this->imageFilePath = 'initial';
}
}
/**
* #ORM\PrePersist()
* #ORM\PreUpdate
*/
public function preUpload() {
if (null !== $this->getFile()) {
// do whatever you want to generate a unique name
$fileName = sha1(uniqid(mt_rand(), true));
$this->imageFilePath = $fileName . '.' . $this->getFile()->guessExtension();
}
}
/**
* #ORM\PostPersist()
* #ORM\PostUpdate
*/
public function upload() {
if (null === $this->getFile()) {
return;
}
// if there is an error when moving the file, an exception will
// be automatically thrown by move(). This will properly prevent
// the entity from being persisted to the database on error
$this->getFile()->move($this->getUploadRootDir(), $this->imageFilePath);
// check if we have an old image
if (isset($this->temp)) {
// delete the old image
unlink($this->getUploadRootDir() . '/' . $this->temp);
// clear the temp image path
$this->temp = null;
}
$this->imageFilePath = null;
}
/**
* #ORM\PostRemove()
*/
public function removeUpload() {
$file = $this->getAbsolutePath();
if ($file) {
unlink($file);
}
}
/**
* Get file.
*
* #return UploadedFile
*/
public function getFile() {
return $this->file;
}
public function getAbsolutePath() {
return null === $this->imageFilePath
? null
: $this->getUploadRootDir() . '/' . $this->imageFilePath;
}
public function getWebPath() {
return null === $this->imageFilePath
? null
: $this->getUploadDir() . '/' . $this->imageFilePath;
}
public function getUploadRootDir() {
// the absolute path where uploaded
// documents should be saved
return __DIR__.'/../../../web/' . $this->getUploadDir();
}
public function getUploadDir() {
// get rid of the __DIR__ so it doesn't screw up
// when displaying uploaded doc/image in the view
return 'uploads/images';
}
/**
* Set album
*
* #param \PhotoGalleryBundle\Entity\Album $album
* #return Image
*/
public function setAlbum(\PhotoGalleryBundle\Entity\Album $album = null)
{
$this->album = $album;
return $this;
}
/**
* Get album
*
* #return \PhotoGalleryBundle\Entity\Album
*/
public function getAlbum()
{
return $this->album;
}
}
ImageType:
<?php
namespace PhotoGalleryBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class ImageType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('imageCaptation')
->add('imageName')
->add('file', 'file', array('multiple' => TRUE))
->add('album')
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'PhotoGalleryBundle\Entity\Image'
));
}
/**
* #return string
*/
public function getName()
{
return 'photogallerybundle_image';
}
}
In this case the value will be an array of UploadedFile objects. Given that you have a type with multiple files yet only one caption, name, etc I assume you will want to refactor Image to support multiple image files. In this case the file property would be better known as files and setFiles should accept an array.
If however you want have one Image entity per file uploaded, consider implementing a collection instead.
Alternatively you could manually process the form in your action. For example:
public function uploadAction(Request $request)
{
foreach ($request->files as $uploadedFile) {
$uploadedFile = current($uploadedFile['file']);
// Build Image using each uploaded file
}
...
I am stopped by this error:
Catchable Fatal Error: Argument 1 passed to
Joker\CoreBundle\Entity\Incidentfile::setFile() must be an instance of
Symfony\Component\HttpFoundation\File\UploadedFile, string given,
called in
/Applications/MAMP/htdocs/joker-repo/vendor/symfony/symfony/src/Symfony/Component/Form/Util/PropertyPath.php
on line 538 and defined in
/Applications/MAMP/htdocs/joker-repo/src/Joker/CoreBundle/Entity/Incidentfile.php
line 157
In my entity I have setters and getters for File. I used this method to make file Upload: THIS
And there was permission problem for folder upload_images but after i solved it everything worked fine but now something went wrong.
Here is entity
/**
* Incidentfile
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="Joker\CoreBundle\Entity\IncidentfileRepository")
* #ORM\HasLifecycleCallbacks
*/
class Incidentfile
{
//
// /**
// * #ORM\ManyToOne(targetEntity="Incidentlist", inversedBy="ListFiles")
// * #ORM\JoinColumn(name="IncidentListId", referencedColumnName="id")
// */
// protected $FileList;
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var \DateTime
*
* #ORM\Column(name="createdat", type="datetime")
*/
private $createdat;
/**
* Image path
*
* #var string
*
* #ORM\Column(type="text", length=255, nullable=false)
*/
protected $path;
/**
* Image file
*
* #var File
*
* #Assert\File(
* maxSize = "5M",
* mimeTypes = {"image/jpeg", "image/gif", "image/png", "image/tiff"},
* maxSizeMessage = "The maxmimum allowed file size is 5MB.",
* mimeTypesMessage = "Only the filetypes image are allowed."
* )
*/
protected $file;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set createdat
*
* #param \DateTime $createdat
* #return Incidentfile
*/
public function setCreatedat($createdat)
{
$this->createdat = $createdat;
return $this;
}
/**
* Get createdat
*
* #return \DateTime
*/
public function getCreatedat()
{
return $this->createdat;
}
/**
* Called before saving the entity
*
* #ORM\PrePersist()
* #ORM\PreUpdate()
*/
public function preUpload()
{
if (null !== $this->file) {
// do whatever you want to generate a unique name
$filename = sha1(uniqid(mt_rand(), true));
$this->path = $filename.'.'.$this->file->guessExtension();
}
}
/**
* Called before entity removal
*
* #ORM\PreRemove()
*/
public function removeUpload()
{
if ($file = $this->getAbsolutePath()) {
unlink($file);
}
}
public function getWebPath()
{
return null === $this->path
? null
: $this->getUploadDir().'/'.$this->path;
}
/**
* Called after entity persistence
*
* #ORM\PostPersist()
* #ORM\PostUpdate()
*/
protected function getUploadRootDir()
{
// the absolute directory path where uploaded
// documents should be saved
return __DIR__.'/../../../../web/'.$this->getUploadDir();
}
protected function getUploadDir()
{
// get rid of the __DIR__ so it doesn't screw up
// when displaying uploaded doc/image in the view.
return 'uploaded_images';
}
/**
* Sets file.
*
* #param UploadedFile $file
*/
public function setFile(UploadedFile $file = null)
{ if (null === $file) {
return;
}
$this->file = $file;
if(in_array($file->getMimeType(),array("image/jpeg", "image/gif", "image/png", "image/tiff"))){
$filename=rand(100000,1000000).'_'.$file->getClientOriginalName();
$file->move($this->getUploadRootDir(),$filename
);
$this->path =$filename;
$this->file = null;
}
else $this->path=null;
}
/**
* Get file.
*
* #return UploadedFile
*/
public function getFile()
{
return $this->file;
}
public function upload() {
// the file property can be empty if the field is not required
if (null === $this->getFile()) {
return;
}
$file=$this->getFile();
$filename=rand(100000,1000000).'_'.$file->getClientOriginalName();
// we use the original file name here but you should
// sanitize it at least to avoid any security issues
// move takes the target directory and target filename as params
$file->move($this->getUploadRootDir(),$filename
);
// set the path property to the filename where you've saved the file
$this->path =$filename;
// clean up the file property as you won't need it anymore
$this->setFile(null);
}
/**
* Set path
*
* #param string $path
* #return Incidentfile
*/
public function setPath($path)
{
$this->path = $path;
return $this;
}
/**
* Get path
*
* #return string
*/
public function getPath()
{
return $this->path;
}
/**
* Set FileList
*
* #param \Joker\CoreBundle\Entity\Incidentlist $fileList
* #return Incidentfile
*/
public function setFileList(\Joker\CoreBundle\Entity\Incidentlist $fileList = null)
{
$this->FileList = $fileList;
return $this;
}
/**
* Get FileList
*
* #return \Joker\CoreBundle\Entity\Incidentlist
*/
public function getFileList()
{
return $this->FileList;
}
}
And here is my controler:
public function TestAction(Request $request){
$incfileRepo = new Incidentfile();
$formfile = $this->createForm(new IncfileType(), $incfileRepo);
if ($request->isMethod('POST')) {
$formfile->bind($request);
if ($formfile->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($incfileRepo);
$em->flush();
return $this->redirect($this->generateUrl('incident_show'));
}
}
$spotEntity = $this->getCurrentSpot();
$sentryEntity = $this->getCurrentSentry();
$messagesCollection = $this->getDoctrine()->getRepository('JokerCoreBundle:Message')->findBy(array(
'spot' => $spotEntity,
'sentry' => $sentryEntity
), array(
'sent_date' => 'DESC'
));
return $this->render('JokerAdminBundle:incidents:addfullform.html.twig', $this->getViewConstants(array(
'formfile'=>$formfile->createView(),
'spot' => $spotEntity,
'sentry' => $sentryEntity,
'messagesCollection' => $messagesCollection,
)));
}
Form in twig:
<form action="" method="post">
{{ form_rest(formfile) }}
<div class="singleTableForm">
<input style="float: left; margin-left: 338px; " type="submit" name="" class="button" value="Add" />
</div>
</form>
I found out what was wrong.. In twig was problem:
<form action="" method="post" {{ form_enctype(formfile) }}>
Just add **{{ form_enctype(formfile) }}**
You must add annotation
/**
* #ORM\PostPersist()
* #ORM\PostUpdate()
*/
public function upload()
see more http://symfony.com/doc/current/cookbook/doctrine/file_uploads.html
And show the form code
UPD: best way - use tags {{ form_start(form) }} and {{ form_end(form) }} it will also protect you from csrf attacks