Uploadable behavior provides the tools to manage the persistance of files with Doctrine 2, including automatic handling of moving, renaming and removal of files and other features.
Features:
Content:
Read the documentation or check the example code on how to setup and use the extensions in most optimized way.
You have three choices to configure the path. You can set a default path on the listener, which will be used on every entity which doesn't have a path or pathMethod defined:
$listener->setDefaultPath('/my/path');
You can use the Uploadable "path" option to set the path:
/**
* @ORM\Entity
* @Gedmo\Uploadable(path="/my/path")
*/
class File
{
//...
}
Or you can use the Uploadable "pathMethod" option to set the name of the method which will return the path:
/**
* @ORM\Entity
* @Gedmo\Uploadable(pathMethod="getPath")
*/
class File
{
public function getPath()
{
return '/my/path';
}
}
The Uploadable interface is not necessary, except in cases there you need to identify an entity as Uploadable. The metadata is loaded only once then you need to identify an entity as Uploadable. The metadata is loaded only once then cache is activated
<?php
namespace Entity;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
// If you don't set the path here, remember that you must set it on the listener!
/**
* @ORM\Entity
* @Gedmo\Uploadable
*/
class File
{
// Other fields..
/**
* @ORM\Column(name="path", type="string")
* @Gedmo\UploadableFilePath
*/
private $path;
}
<?php
namespace Entity;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @Gedmo\Uploadable(path="/my/path", callback="myCallbackMethod", filenameGenerator="SHA1", allowOverwrite=true, appendNumber=true)
*/
class File
{
/**
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @ORM\Column(name="path", type="string")
* @Gedmo\UploadableFilePath
*/
private $path;
/**
* @ORM\Column(name="mime_type", type="string")
* @Gedmo\UploadableFileMimeType
*/
private $mimeType;
/**
* @ORM\Column(name="size", type="decimal")
* @Gedmo\UploadableFileSize
*/
private $size;
public function myCallbackMethod(array $info)
{
// Do some stuff with the file..
}
// Other methods..
}
Yaml mapped Article: /mapping/yaml/Entity.Article.dcm.yml
---
Entity\File:
type: entity
table: files
gedmo:
uploadable:
allowOverwrite: true
appendNumber: true
path: '/my/path'
pathMethod: getPath
callback: callbackMethod
filenameGenerator: SHA1
id:
id:
type: integer
generator:
strategy: AUTO
fields:
path:
type: string
gedmo:
- uploadableFilePath
mimeType:
type: string
gedmo:
- uploadableFileMimeType
size:
type: decimal
gedmo:
- uploadableFileSize
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:gedmo="http://gediminasm.org/schemas/orm/doctrine-extensions-mapping">
<entity name="Entity\File" table="files">
<id name="id" type="integer" column="id">
<generator strategy="AUTO"/>
</id>
<field name="mimeType" column="mime" type="string">
<gedmo:uploadable-file-mime-type />
</field>
<field name="size" column="size" type="decimal">
<gedmo:uploadable-file-size />
</field>
<field name="path" column="path" type="string">
<gedmo:uploadable-file-path />
</field>
<gedmo:uploadable
allow-overwrite="true"
append-number="true"
path="/my/path"
path-method="getPath"
callback="callbackMethod"
filename-generator="SHA1" />
</entity>
</doctrine-mapping>
<?php
// Example setting the path directly on the listener:
$listener->setDefaultPath('/my/app/web/upload');
if (isset($_FILES['images']) && is_array($_FILES['images'])) {
foreach ($_FILES['images'] as $fileInfo) {
$file = new File();
$listener->addEntityFileInfo($file, $fileInfo);
// You can set the file info directly with a FileInfoInterface object, like this:
//
// $listener->addEntityFileInfo($file, new FileInfoArray($fileInfo));
//
// Or create your own class which implements FileInfoInterface
//
// $listener->addEntityFileInfo($file, new MyOwnFileInfo($fileInfo));
$em->persist($file);
}
}
$em->flush();
Easy like that, any suggestions on improvements are very welcome.
Maybe you want to handle files obtained from an URL, or even files that are already located in the same server than your app. This can be handled in a very simple way. First, you need to create a class that implements the FileInfoInterface interface. As an example:
use Gedmo\Uploadable\FileInfo\FileInfoInterface;
class CustomFileInfo implements FileInfoInterface
{
protected $path;
protected $size;
protected $type;
protected $filename;
protected $error = 0;
public function __construct($path)
{
$this->path = $path;
// Now, process the file and fill the rest of the properties.
}
// This returns the actual path of the file
public function getTmpName()
{
return $path;
}
// This returns the filename
public function getName()
{
return $this->name;
}
// This returns the file size in bytes
public function getSize()
{
return $this->size;
}
// This returns the mime type
public function getType()
{
return $this->type;
}
public function getError()
{
// This should return 0, as it's only used to return the codes from PHP file upload errors.
return $this->error;
}
// If this method returns true, it will produce that the extension uses "move_uploaded_file" function to move
// the file. If it returns false, the extension will use the "copy" function.
public function isUploadedFile()
{
return false;
}
}
Or you could simply extend the FileInfoArray class and do the following:
use Gedmo\Uploadable\FileInfo\FileInfoArray;
class CustomFileInfo extends FileInfoArray
{
public function __construct($path)
{
// There's already a $fileInfo property, which needs to be an array with the
// following keys: tmp_name, name, size, type, error
$this->fileInfo = array(
'tmp_name' => '',
'name' => '',
'size' => 0,
'type' => '',
'error' => 0
);
// Now process the file at $path and fill the keys with the correct values.
//
// In this example we use a $path as the first argument, but it could be an URL
// to the file we need to obtain, etc.
}
public function isUploadedFile()
{
// Remember to set this to false so we use "copy" instead of "move_uploaded_file"
return false;
}
}
And that's it. Then, instead of getting the file info from the $_FILES array, you would do:
// We set the default path in the listener again
$listener->setDefaultPath('/my/path');
$file = new File();
$listener->addEntityFileInfo($file, new CustomFileInfo('/path/to/file.txt'));
$em->persist($file);
$em->flush();
If you want to use your own mime type guesser, you need to implement the interface "Gedmo\Uploadable\MimeType\MimeTypeGuesserInterface", which has only one method: "guess($filePath)". Then, you can set the mime type guesser used on the listener in the following way:
$listener->setMimeTypeGuesser(new MyCustomMimeTypeGuesser());