Hewwo rashidkhan~
Symfony doc is quite complete on the upload process, did you read it?
http://symfony.com/doc/current/controller/upload_file.html
After a few modifications, I choose to use it as service.
Here is the process:
1) Add a few parameters to app/config/config.yml
:
under parameters
:
parameters:
locale: en
profile_directory: '%kernel.root_dir%/../web/upload/profile'
another_directory: '%kernel.root_dir%/../web/upload/another'
under twig
twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
globals:
profile_directory: '/upload/profile/'
another_directory: '/upload/another/'
The two profile_directory
added just now will be used as variables in both your upload service and twig to point the targer directory.
I added another_directory
to explain something more a bit after.
2) Create the service:
Create a new file under src/YourBundle/Services/FileUploader.php
From here, my code is a bit different than what you can find on the Symfony site.
FileUploader.php
content:
<?php
namespace YourBundleServices;
use YourBundleEntityProfileModel;
use YourBundleEntityAnother;
class FileUploader {
private $profileDir;
private $anotherDir;
public function __construct($profileDir) {
$this->profileDir=$profileDir;
$this->anotherDir=$anotherDir;
}
public function upload($class) {
if($class instanceof ProfileModel) {
$file=$class->getPicture();
$fileName='picture-'.uniqid().'.'.$file->guessExtension();
$file->move($this->profileDir, $fileName);
$class->setPicture($fileName);
}
if($class instanceof Another) {
$file=$class->getPicture();
$fileName='picture-'.uniqid().'.'.$file->guessExtension();
$file->move($this->anotherDir, $fileName);
$class->setPicture($fileName);
}
return $class;
}
}
3) Register the service to app/config/services.yml
:
under services
:
services:
app.file_uploader:
class: YourBundleServicesFileUploader
arguments:
- '%profile_directory%'
- '%another_directory%'
Each argument must be in the same order as your private
in the FileUploader.php
file.
Those arguments are the ones we setted in app/config/config.yml
under parameters
.
4) Edit your controller:
The controller part is quite simple.
Add use SymfonyComponentHttpFoundationFileFile;
in the import section
Under newAction
public function newAction(Request $request)
{
$profileModel = new ProfileModel();
$form = $this->createForm('YourBundleFormProfileModelType', $profileModel);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// We upload the file with this line
$profileModel=$this->get('app.file_uploader')->upload($profileModel);
$em = $this->getDoctrine()->getManager();
$em->persist($profileModel);
$em->flush();
return $this->redirectToRoute('profile_model_show', array('id' => $profileModel->getId()));
}
return $this->render('YourBundle:Default:new.html.twig', array(
'profileModel' => $profileModel,
'form' => $form->createView(),
));
}
Under editAction
public function editAction(Request $request, ProfileModel $profileModel)
{
// Add this live above everything else in the code.
$profileModel->setPicture(new File($this->getParameter('profile_directory').'/'.$profileModel->getPicture()));
[...]
}
I haven't gone more far, so I can only explain what to modify after...
In your editAction
, you will also have to check that $_FILES isn't empty.
If it's not, then you do the upload process.
If it's, then make sure to not edit the picture
column in the SQL query (you will have to do a custom query)
5) Your twig views:
Under show.html.twig
Change
<tr>
<th>Picture</th>
<td>{{ profileModel.picture) }}</td>
</tr>
to
<tr>
<th>Picture</th>
<td><img src="{{ asset(profile_directory~profileModel.picture) }}"></td>
</tr>
Same goes for the index.html.twig
.
And you can add (not replace) it to the edit.html.twig
to get a preview of the actual picture.
6) Explanations:
In app/config/config.yml
we added a few directory to use as parameters in your files.
It will later make it easier to change those directories if needed. (Won't have to edit tons of files... YAY!)
Twig directories always start from the /web
folder.
Those directory are used when we register our service as arguments
.
They will set our variable in the service file FileUploader.php
.
Unlike the Symfony site exemple, we pass the whole object to the upload service.
We then, check from which class this object was created and do our upload process based in it.
Your upload process in the controller is then shortened to a single line.
In twig, we will also use the directory variable set in app/config/config.yml
undet the twig
property.
Like said above, if our upload directory change, we will then just have to edit the app/config/config.yml
file.
I hope this will help you solve your upload issues.
Cordially,
Preciel.