byteincoffee/doctrine-extensions
Laravel package integrating Doctrine Extensions with Eloquent models, adding behaviors like timestampable, sluggable, soft delete, and more. Provides easy configuration, listeners/subscribers, and seamless use of Doctrine-style extensions in Laravel apps.
Uploadable will automate for you storing files as a field of entity.
Features:
First argument must be an array with filesystems, where keys are later identifiers of filesystems. Each filesystem must be instance of Gaufrette\Filesystem.
<?php
use Gaufrette\Filesystem;
use Gaufrette\Adapter;
$filesystem1 = new Filesystem(new Adapter\Local('/some/path'));
$filesystem2 = new Filesystem(new Adapter\Ftp('/other/path', 'example.com'));
$filesystems = array(
'filesystem1' => $filesystem1,
'filesystem2' => $filesystem2,
);
Second argument defines class, that will handle conversion of anything you put as file into instance of FSi\DoctrineExtensions\Uploadable\File.
You can define default file handler as:
<?php
use FSi\DoctrineExtensions\Uploadable\FileHandler;
$handler = new FileHandler\ChainHandler(array(
new FileHandler\GaufretteHandler(),
new FileHandler\SplFileInfoHandler(),
));
This configuration will allow you to handle instances of Gaufrette\File (including FSi\DoctrineExtensions\Uploadable\File) and SplFileInfo.
File handler must be instance of FSi\DoctrineExtensions\Uploadable\FileHandler\FileHandlerInterface.
use Doctrine\Common\EventManager;
use FSi\DoctrineExtensions\Uploadable\UploadableListener
use FSi\DoctrineExtensions\Uploadable\Keymaker\Entity;
$evm = new EventManager();
$uploadableListener = new UploadableListener($filesystems, $fileHandler, $keymaker);
$evm->addEventSubscriber($uploadableListener);
// now this event manager should be passed to entity manager constructor
// It's good idea to set default filesystem if you want to use uploadable without
// specifying filesystem.
$uploadableListener->setDefaultFilesystem($filesystem1);
// It's also good idea to set default keymaker if you want to use uploadable without
// specifying keymaker.
$keymaker = new Entity();
$uploadableListener->setDefaultKeymaker($keymaker);
// It must be instance of FSi\DoctrineExtensions\Uploadable\Keymaker\KeymakerInterface.
You can find documentation to keymaker shipped with uploadable extension here /doc/uploadable/keymaker.md.
FSi\DoctrineExtensions\Uploadable\Keymaker\KeymakerInterfaceHere is an example of an entity with uploadable property:
<?php
namespace Acme\DemoBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use FSi\DoctrineExtensions\Uploadable\Mapping\Annotation\Uploadable;
use Symfony\Component\Validator\Constraints as Assert;
/**
* [@ORM](https://github.com/ORM)\Table()
* [@ORM](https://github.com/ORM)\Entity()
*/
class User
{
/**
* [@var](https://github.com/var) integer
*
* [@ORM](https://github.com/ORM)\Column(type="integer")
* [@ORM](https://github.com/ORM)\Id
* [@ORM](https://github.com/ORM)\GeneratedValue(strategy="AUTO")
*/
public $id;
/**
* [@var](https://github.com/var) string
*
* [@ORM](https://github.com/ORM)\Column(length=255)
*/
public $name;
/**
* [@ORM](https://github.com/ORM)\Column(length=255, nullable=true)
* [@Uploadable](https://github.com/Uploadable)(targetField="file", filesystem="filesystem1")
*/
protected $fileKey;
protected $file;
public function setFileKey($key)
{
$this->fileKey = $key;
}
public function getFileKey()
{
return $this->fileKey;
}
public function setFile($file)
{
if (!empty($file)) {
$this->file = $file;
}
}
public function getFile()
{
return $this->file;
}
public function removeFile()
{
$this->file = null;
}
}
Note that both $fileKey and $file properties MUST have defined getters and setters.
There is also example with xml mapping - /doc/uploadable/xml.md and yaml mapping /doc/uploadable/yaml.md.
FSi\DoctrineExtensions\Uploadable\Keymaker\KeymakerInterfaceIn every exeample below class Acme\DemoBundle\Entity\User is as defined above.
<?php
use Acme\DemoBundle\Entity\User;
$user = new User();
$user->setFile($file); // $file must be instances of something, that $fileHandler can handle.
$entityManager->persist($user);
$entityManager->flush();
$user->getFileKey(); // Returns new key of file.
$user->getFile()->getKey(); // Returns the same as line above, but you must check if getFile doesn't return null.
$tmpFile1 = $user->getFile(); // Instance of FSi\DoctrineExtensions\Uploadable\File.
$tmpFile1->exists(); // true
<?php
use Acme\DemoBundle\Entity\User;
// $user = (...) // Obtain instance of User from database.
$file1 = $user->getFile();
$user->setFile($file2);
$entityManager->flush();
$file1->exists(); // false
Note, that old file, that was attached to entity earlier was automatically deleted.
You can delete single file from entity.
<?php
use Acme\DemoBundle\Entity\User;
// $user = (...) // Obtain instance of User from database.
$file = $user->getFile();
$user->removeFile();
$entityManager->flush();
$file2->exists(); // false
Or you can just delete whole entity. All its files will be deleted automatically with that entity.
<?php
use Acme\DemoBundle\Entity\User;
// $user = (...) // Obtain instance of User from database.
$file = $user->getFile();
$entityManager->remove($user);
$entityManager->flush();
$file2->exists(); // false
If file is already attached, you can modify file directly.
<?php
$user->getFile()->setContent('some content');
Heads up! This way if something fails, changes won't be undone! Remember that replacing it with something new is much more safer, so preferable way is:
<?php
$file = new \SplFileInfo(tempname(sys_get_tmp_dir(), ''));
$fileObj = $file->openFile('a');
$fileObj->fwrite('some content');
$user->setFile($file);
If you update/delete file and flush will raise an exception, old files will still be present.
<?php
try {
$file1 = $user->getFile1();
$user->removeFile();
$file2 = $user->getFile2();
$user->setFile2($someFile);
$entityManager->flush(); // Exception.
} catch (Exception $e) {
$file1->exists(); // true
$file2->exists(); // true
}
Heads up! Usually new files (in case of update) will be created, so after such case (like above) there is big chance that new files exists, but aren't bounded to any entity through key.
If you turn of auto commit, it is up to you to backup old files!
<?php
$entityManager->getConnection()->beginTransaction(); // Suspend auto-commit.
try {
$file1 = $user->getFile1();
$user->removeFile();
$file2 = $user->getFile2();
$user->setFile2($someFile);
$entityManager->flush(); // Exception.
$entityManager->getConnection()->commit();
} catch (Exception $e) {
$entityManager->getConnection()->rollback();
$entityManager->close();
$file1->exists(); // false
$file2->exists(); // false
}
How can I help you explore Laravel packages today?