ashleydawson/doctrine-gaufrette-storable-bundle
Installation:
composer require ashleydawson/doctrine-gaufrette-storable-bundle:0.8.*
Register the bundle in AppKernel.php:
new AshleyDawson\DoctrineGaufretteStorableBundle\AshleyDawsonDoctrineGaufretteStorableBundle(),
new Knp\Bundle\GaufretteBundle\KnpGaufretteBundle(), // Required dependency
Configure Gaufrette:
Add a filesystem adapter in config.yml:
knp_gaufrette:
adapters:
local_adapter:
local:
directory: %kernel.root_dir%/../uploads
filesystems:
default:
adapter: local_adapter
Apply the Trait:
Use UploadedFileTrait in your Doctrine entity:
use AshleyDawson\DoctrineGaufretteStorableBundle\Model\UploadedFileTrait;
class Post
{
use UploadedFileTrait;
// ... existing fields
public function getFilesystemMapId()
{
return 'default'; // Matches your knp_gaufrette config
}
}
Update Schema:
php app/console doctrine:schema:update --force
First Use Case: Create a form with a file field and bind it to your entity:
$builder->add('uploaded_file', 'file', ['required' => false]);
File Upload Handling:
Product, UserProfile).file_name, file_mime_type, file_size).file_storage_path).Form Integration:
uploaded_file (or proxy via a custom setter).$form = $this->createForm(PostType::class, $post);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em->persist($post);
$em->flush();
}
File Retrieval:
FileSystem service to read files:
$fileSystem = $this->get('knp_gaufrette.filesystem.default');
$file = $fileSystem->read($post->getFileStoragePath());
Lifecycle Events:
StorageEvents::PRE_WRITE) to customize file paths or metadata:
$dispatcher->addListener(StorageEvents::PRE_WRITE, function (WriteUploadedFileEvent $event) {
$event->setFileStoragePath('custom/' . $event->getFileName());
});
Validation: Add constraints to validate file types/sizes:
use Symfony\Component\Validator\Constraints as Assert;
/**
* @Assert\File(
* maxSize="1024k",
* mimeTypes={"image/jpeg", "image/png"}
* )
*/
public function getUploadedFile()
{
return $this->uploaded_file;
}
Symfony 4+: Use autowiring for services (e.g., FilesystemManager):
public function __construct(private FilesystemManager $filesystemManager) {}
Testing: Mock UploadedFile and Filesystem in unit tests:
$uploadedFile = $this->createMock(UploadedFile::class);
$uploadedFile->method('getClientOriginalName')->willReturn('test.jpg');
$post->setUploadedFile($uploadedFile);
Schema Updates:
doctrine:schema:update after adding the trait will cause errors.Filesystem Configuration:
getFilesystemMapId() and knp_gaufrette config keys will fail silently.getFilesystemMapId().File Overwrites:
image.jpg).StorageEvents::PRE_WRITE to generate unique paths (e.g., UUIDs).ORM vs. ODM:
Event Dispatcher:
EventDispatcher, not Doctrine’s lifecycle callbacks.event_dispatcher service is available (it is by default in Symfony).Missing Files:
directory in knp_gaufrette adapters exists and is writable.file_storage_path in the database matches the filesystem structure.Validation Errors:
dump($form->getErrors()) to debug form validation issues.Events Not Triggering:
Custom Storage Logic:
setUploadedFile) to add pre-processing:
public function setUploadedFile(UploadedFile $file = null)
{
if ($file) {
$this->file_name = 'prefix_' . $file->getClientOriginalName();
}
parent::setUploadedFile($file);
}
Multiple Files:
PostImage).Cloud Storage:
aws_s3) without changing entity logic.Soft Deletes:
StorageEvents::PRE_DELETE to archive files before "deleting" them:
$dispatcher->addListener(StorageEvents::PRE_DELETE, function (DeleteUploadedFileEvent $event) {
$fileSystem->write('archive/' . $event->getFileName(), $event->getFileContent());
});
cache:clear) if changes don’t apply.www-data) has write access to the storage directory.How can I help you explore Laravel packages today?