Installation
composer require antonio150/uploadimagebundle
Register the bundle in config/bundles.php (Symfony) or config/app.php (Laravel via Symfony bridge):
return [
// ...
Antonio150\UploadImageBundle\Antonio150UploadImageBundle::class => ['all' => true],
];
Configuration Publish the default config:
php artisan vendor:publish --tag=uploadimagebundle-config
Update config/upload_image.php to define:
upload_dir (e.g., storage/app/public/uploads)allowed_extensions (e.g., ['jpg', 'png', 'webp'])max_size (e.g., 2MB)First Use Case Create a controller method to handle uploads:
use Antonio150\UploadImageBundle\Form\ImageType;
use Antonio150\UploadImageBundle\Service\ImageUploader;
public function upload(Request $request, ImageUploader $uploader)
{
$form = $this->createForm(ImageType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$file = $form->get('image')->getData();
$path = $uploader->upload($file);
return response()->json(['path' => $path]);
}
}
Form Setup
Use ImageType to define a form field for file uploads:
$builder->add('image', FileType::class, [
'label' => 'Upload Image',
'mapped' => false,
'required' => true,
]);
Validation
Leverage Symfony’s built-in validation (e.g., NotBlank, File) or extend ImageType to add custom rules:
$builder->add('image', FileType::class, [
'constraints' => [
new File([
'maxSize' => '2048k',
'mimeTypes' => ['image/jpeg', 'image/png'],
'mimeTypesMessage' => 'Please upload an image (JPEG/PNG).',
]),
],
]);
Upload Logic
Inject ImageUploader service and call upload():
$path = $uploader->upload($file, [
'folder' => 'user_avatars', // Optional subfolder
'rename' => true, // Auto-generate filename
]);
Post-Processing
Use the returned path ($path) to store in a database or generate URLs:
$url = asset('storage/' . $path); // Laravel asset helper
Storage facade for path handling:
use Illuminate\Support\Facades\Storage;
$filePath = $uploader->upload($file);
$url = Storage::url($filePath);
AppServiceProvider:
$this->app->bind(ImageUploader::class, function ($app) {
return new ImageUploader($app['config']['upload_image']);
});
ImageUploadedEvent (if the bundle emits events; check source).Permissions
Ensure the upload_dir is writable by the web server:
chmod -R 775 storage/app/public/uploads
Laravel: Use storage:link to symlink public/uploads:
php artisan storage:link
File Overwrites
The bundle defaults to not overwriting files. Set 'rename' => true in upload() to avoid conflicts:
$uploader->upload($file, ['rename' => true]);
MIME Type Spoofing Validate MIME types server-side (client-side checks are bypassable):
$builder->add('image', FileType::class, [
'mimeTypes' => ['image/jpeg', 'image/png'],
]);
Symfony vs. Laravel Quirks
FormComponent. In Laravel, ensure you’re using a bridge (e.g., laravel/symfony).form_start, configure Laravel’s router to handle _token fields.Log Uploads: Enable debug mode in config/upload_image.php:
'debug' => env('APP_DEBUG', false),
Check storage/logs/laravel.log for upload errors.
Test Locally: Use php artisan serve and test uploads with Postman or browser dev tools (check Network tab for file payloads).
Custom Filename Generator
Override the default ImageUploader to use a custom strategy (e.g., UUIDs):
$uploader->upload($file, [
'rename' => true,
'filename_generator' => function ($file) {
return Str::uuid() . '.' . $file->getClientOriginalExtension();
},
]);
Post-Upload Actions
Hook into the upload process by extending ImageUploader:
class CustomImageUploader extends ImageUploader
{
protected function afterUpload($file, $path)
{
// Example: Generate thumbnails
Image::make($path)->resize(100, 100)->save(public_path('thumbs/' . $path));
}
}
Cloud Storage
Replace the default filesystem adapter by binding a custom Filesystem service:
$this->app->bind(\League\Flysystem\Filesystem::class, function () {
return Storage::disk('s3')->getAdapter()->getFilesystem();
});
upload_dir is relative to the project root (e.g., storage/app/public/uploads), not the public folder..env for dynamic paths:
'upload_dir' => env('UPLOAD_DIR', 'storage/app/public/uploads'),
How can I help you explore Laravel packages today?