Installation
composer require qcod/laravel-imageup
The package auto-registers; no manual provider setup is needed unless customizing config.
Apply Trait to Model
Add HasImageUploads to your Eloquent model and define $imageUploads:
use QCod\ImageUp\HasImageUploads;
class Product extends Model
{
use HasImageUploads;
protected $imageUploads = [
'image' => [
'path' => 'products/{id}',
'disk' => 'public',
'width' => 800,
'height' => 600,
'crop' => true,
],
'thumbnail' => [
'path' => 'products/thumbs/{id}',
'disk' => 'public',
'width' => 200,
'height' => 200,
'crop' => false,
],
];
}
First Use Case
Upload an image via a form with the field name matching the key in $imageUploads (e.g., image). The trait handles:
Example request payload:
{
"name": "Example Product",
"image": "base64_encoded_image_or_file_upload"
}
Form Handling
Use the uploadImage method in your controller:
public function store(Request $request)
{
$product = new Product();
$product->name = $request->name;
$product->uploadImage($request->file('image')); // Handles upload/resize
$product->save();
}
Dynamic Uploads
For dynamic field names (e.g., galleries), use the uploadImage method with a custom key:
$product->uploadImage($request->file('gallery_image'), 'gallery_image');
Batch Processing Process multiple images in a loop:
foreach ($request->file('images') as $file) {
$product->uploadImage($file, 'gallery_' . $loop->index);
}
Validation: Extend validation rules in validateImageUpload (override the trait method):
public function validateImageUpload($field, $request)
{
$this->validate($request, [
$field => 'required|image|mimes:jpeg,png|max:2048',
]);
}
Custom Storage: Override getImageDisk to use different disks per field:
protected function getImageDisk($field)
{
return $field === 'thumbnail' ? 's3' : 'public';
}
Events: Listen for imageup.uploading, imageup.uploaded, or imageup.deleting events:
event(new ImageUploading($model, $field, $file));
API Responses: Return URLs with getImageUrl:
return response()->json([
'url' => $product->getImageUrl('image'),
]);
Field Name Mismatch
$imageUploads keys exactly. Case-sensitive.dd($request->file()) to verify field names.Missing Disk Configuration
config/filesystems.php for the specified disk (e.g., public).php artisan vendor:publish --tag=imageup-config) and verify paths.Intervention Image Dependencies
intervention/image. Install if missing:
composer require intervention/image
Crop Conflicts
crop: true but no width/height are set, the package silently skips cropping.Database Column Requirements
path and size (e.g., image_path, image_size).$fillable.Log Upload Events: Add a listener to debug:
ImageUp::addListener('uploading', function ($event) {
\Log::info('Uploading', $event->toArray());
});
Check File Permissions: Ensure the storage path is writable:
chmod -R 775 storage/app/public
Custom Paths Dynamically generate paths using closures:
'path' => function ($model) {
return "products/{$model->category_slug}/{$model->id}";
},
Post-Processing
Hook into imageup.uploaded to run additional logic (e.g., generate PDF thumbnails):
ImageUp::addListener('uploaded', function ($event) {
// $event->model, $event->field, $event->path
});
Fallback for Missing Fields Skip non-existent fields gracefully:
if (method_exists($model, 'uploadImage')) {
$model->uploadImage($file, $field);
}
Testing Mock the trait in tests:
$model = new class extends Model {
use HasImageUploads;
protected $imageUploads = ['test' => ['path' => 'test']];
};
How can I help you explore Laravel packages today?