Installation
composer require arthem/file-bundle
Add to config/bundles.php:
return [
// ...
Arthem\FileBundle\ArthemFileBundle::class => ['all' => true],
];
First Use Case: File Upload
File type (e.g., User):
use Arthem\FileBundle\Entity\File;
#[ORM\Entity]
class User {
#[ORM\OneToOne(targetEntity: File::class, cascade: ['persist'])]
private ?File $avatar = null;
}
FileType in a Symfony form:
use Arthem\FileBundle\Form\Type\FileType;
$builder->add('avatar', FileType::class, [
'label' => 'Profile Picture',
'mapped' => true,
'allowed_mime_types' => ['image/jpeg', 'image/png'],
'max_size' => '2M',
]);
Key Directories
config/packages/arthem_file.yaml (auto-generated).src/Entity/File.php (core model).src/Service/FileUploader.php (customizable upload logic).src/Doctrine/UploadableListener.php (auto-handles uploads).public/uploads/ (configurable via arthem_file.storage.path).Arthem\FileBundle\Service\FileUploader to integrate with S3, GCS, etc.:
// config/services.yaml
services:
Arthem\FileBundle\Service\FileUploader:
arguments:
$storageAdapter: '@your_custom_storage_service'
FileUploadEvent (dispatches after upload):
use Arthem\FileBundle\Event\FileUploadEvent;
$eventDispatcher->addListener(FileUploadEvent::class, function (FileUploadEvent $event) {
// Example: Generate thumbnails via LiipImagineBundle
$this->imagineManager->resize($event->getFile()->getPath(), new \Imagine\Image());
});
Uploadable trait for quick setup:
use Arthem\FileBundle\Traits\Uploadable;
class Product {
use Uploadable;
// ...
}
# config/packages/doctrine.yaml
doctrine:
orm:
event_subscribers:
- Arthem\FileBundle\Doctrine\UploadableListener
use Symfony\Component\Serializer\Annotation\Groups;
class File {
#[Groups(['api'])]
public function getUrl(): string { ... }
}
FileType resolver (if youshido/graphql-bundle is installed):
type File {
id: ID!
url: String!
size: Int!
}
use Arthem\FileBundle\Validator\Constraints\File;
$builder->add('document', FileType::class, [
'constraints' => [
new File(['maxSize' => '5M', 'mimeTypes' => ['application/pdf']])
]
]);
FilePreUploadEvent:
$eventDispatcher->addListener(FilePreUploadEvent::class, function (FilePreUploadEvent $event) {
$event->setFileName(strtolower($event->getFileName()));
});
arthem_file.imagine:
# config/packages/arthem_file.yaml
arthem_file:
imagine:
enabled: true
filters:
thumbnail:
size: [200, 200]
mode: outbound
{{ file.getImagineUrl('thumbnail') }}
#[ORM\Id]
#[ORM\Column(type: 'uuid', unique: true)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: 'doctrine.uuid_generator')]
private ?UUID $id = null;
FileUploader to fetch remote files:
$file = $fileUploader->uploadFromUrl(
'https://example.com/file.pdf',
'documents',
'file.pdf'
);
Missing Doctrine ORM
Class 'Doctrine\ORM\EntityManager' not found.doctrine/orm in require-dev (not require) if not using ORM:
composer require doctrine/orm --dev
LiipImagineBundle Conflicts
LiipImagineBundle not found.liip/imagine-bundle is installed and configured before arthem/file-bundle.File Permissions
Permission denied.public/uploads/:
chmod -R 775 public/uploads/
chown -R www-data:www-data public/uploads/ # Adjust user as needed
UUID Collisions
uuid_generator or ramsey/uuid for consistency.Event Dispatcher Order
FileUploadEvent listeners may not trigger.UploadableListener is registered after your custom listeners.Log Upload Events
FileUploadEvent:
# config/packages/monolog.yaml
monolog:
handlers:
main:
level: debug
Validate File Paths
arthem_file.storage.path in config.kernel.project_dir vs. public path.Doctrine Proxy Issues
Proxy __CG__\Arthem\FileBundle\Entity\File not found.php bin/console cache:clear
Custom Storage Adapters
Arthem\FileBundle\Service\FileUploader:
class S3FileUploader extends FileUploader {
public function upload(File $file, string $dir): void {
// Custom S3 logic
$this->s3Client->putObject([...]);
}
}
New File Types
namespace App\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
#[Attribute]
class CustomFile extends Constraint {
public string $message = 'Invalid file type.';
}
services.yaml:
services:
App\Validator\Constraints\CustomFileValidator: ~
GraphQL Extensions
use YouShido\GraphQLBundle\Resolver\ResolverInterface;
class FileUrlResolver implements ResolverInterface {
public function resolve($value, array $args, ContextInterface $context) {
return $value->getUrl();
}
}
Doctrine Lifecycle Callbacks
use Arthem\FileBundle\Traits\Uploadable;
class Document {
use Uploadable;
#[ORM\PreRemove]
public function preRemove() {
$this->deleteFile(); // Custom deletion (e.g., soft delete)
}
}
arthem_file.storage.path: Defaults to public/uploads/.How can I help you explore Laravel packages today?