The VichUploaderBundle is a simple Symfony2 bundle that attempts to ease file uploads that are attached to an entity. The bundle will automatically name and save the uploaded file according to the configuration specified on a per property basis. It will also load the file back into the entity upon retrieval from the datastore if configured to do so. The bundle also provides templating helpers for generating URLs to the file. The file can also be configured to be removed from the file system upon removal of the entity.
To install the bundle, place it in the vendor/bundles/Vich/UploaderBundle
directory of your project. You can do this by adding the bundle to your deps file,
as a submodule, cloning it, or simply downloading the source.
Add to deps
file:
[VichUploaderBundle]
git=git://github.com/dustin10/VichUploaderBundle.git
target=/bundles/Vich/UploaderBundle
Or you may add the bundle as a git submodule:
$ git submodule add https://github.com/dustin10/VichUploaderBundle.git vendor/bundles/Vich/UploaderBundle
Next you should add the Vich
namespace to your autoloader:
<?php
// app/autoload.php
$loader->registerNamespaces(array(
// ...
'Vich' => __DIR__.'/../vendor/bundles'
));
To start using the bundle, register the bundle in your application's kernel class:
// app/AppKernel.php
public function registerBundles()
{
$bundles = array(
// ...
new Vich\UploaderBundle\VichUploaderBundle(),
);
)
First configure the db_driver
option. You must specify either orm
or
mongodb
.
# app/config/config.yml
vich_uploader:
db_driver: orm # or mongodb
In order to map configuration options to the property of the entity you first
need to create a mapping in the bundle configuration. You create these mappings
under the mappings
key. Each mapping should have a unique name. So, if you wanted
to name your mapping product_image
, the configuration for this mapping would be
similar to:
vich_uploader:
# ...
mappings:
product_image:
upload_dir: %kernel.root_dir%/../web/images/products
The upload_dir
is the only required configuration option for an entity mapping.
All options are listed below:
upload_dir
: The directory to upload the file tonamer
: The id of the namer service for this entity (See Namers section below)delete_on_remove
: Set to true if the file should be deleted from the filesystem when the entity is removedinject_on_load
: Set to true if the file should be injected into the uploadable field property when it is loaded from the data store. The object will be an instance ofSymfony\Component\HttpFoundation\File\File
Note:
A verbose configuration reference including all configuration options and their default values is included at the bottom of this document.
In order for your entity or document to work with the bundle, you need to add a
few annotations to it. First, annotate your class with the Uploadable
annotation.
This lets the bundle know that it should look for files to upload in your class when
it is saved, inject the files when it is loaded and check to see if it needs to
remove files when it is removed. Next, you should annotate the fields which hold
the instance of Symfony\Component\HttpFoundation\File\UploadedFile
when the form
is submitted with the UploadableField
annotation. The UploadableField
annotation
has a few required options. They are as follows:
mapping
: The mapping specified in the bundle configuration to usefileNameProperty
: The property of the class that will be filled with the file name generated by the bundle
Lets look at an example using a fictional Product
ORM entity:
<?php
namespace Acme\DemoBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraint as Assert;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
/**
* @ORM\Entity
* @Vich\Uploadable
*/
class Product
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
// ..... other fields
/**
* @Assert\File(
* maxSize="1M",
* mimeTypes={"image/png", "image/jpeg", "image/pjpeg"}
* )
* @Vich\UploadableField(mapping="property_image", fileNameProperty="imageName")
*
* @var File $image
*/
protected $image;
/**
* @ORM\Column(type="string", length=255, name="image_name")
*
* @var string $imageName
*/
protected $imageName;
}
The bundle uses namers to name the files it saves to the filesystem. A namer
implements the Vich\UploaderBundle\Naming\NamerInterface
interface. If no namer is
configured for a mapping, the bundle will simply use the name of the file that
was uploaded. if you would like to change this then you must implement a custom namer.
To create a custom namer, simply implement the Vich\UploaderBundle\Naming\NamerInterface
and in the name
method of your class return the desired file name. Since your entity
is passed to the name
method, as well as the field name, you are free to get any information
from it to create the name, or inject any other services that you require.
Note: The name returned should include the file extension as well. This can easily be retrieved from the
UploadedFile
instance using thegetExtension
orguessExtension
depending on what version of PHP you are running.
After you have created your namer and configured it as a service, you simply specify
the service id for the namer
configuration option of your mapping. An example:
vich_uploader:
# ...
mappings:
product_image:
upload_dir: %kernel.root_dir%/../web/images/products
namer: my.namer.product
Here my.namer.product
is the configured id of the service.
To get a url for the file you can use the vich_uploader.templating.helper
service as follows:
$entity = // get the entity..
$helper = $this->container->get('vich_uploader.templating.helper');
$path = $helper->asset($entity, 'image');
or in a Twig template you can use the vich_uploader_asset
function:
<img src="{{ vich_uploader_asset(product, 'image') }}" alt="{{ product.name }}" />
You must specify the annotated property you wish to get the file path for.
Note: The path returned is relative to the web directory which is specified using the
web_dir_name
configuration parameter.
- Currently the bundle only supports generating a relative url for the file.
- Currently the bundle only supports saving/deleting files to the local filesystem.
Below is the full default coniguration for the bundle:
# app/config/config.yml
vich_uploader:
db_driver: orm # or mongodb
web_dir_name: web
twig: true
mappings:
product_image:
upload_dir: ~ # required
namer: ~ # specify a namer service id for this entity, null default
delete_on_remove: true # determines whether to delete file upon removal of entity
inject_on_load: true # determines whether to inject a File instance upon load
# ... more mappings