Install the Package
composer require webplusm/gallery-json-media
Publish the config (if needed):
php artisan vendor:publish --provider="Webplusm\GalleryJsonMedia\GalleryJsonMediaServiceProvider" --tag="config"
Configure the Model
Add a JSON column (e.g., gallery) to your database table:
Schema::table('your_table', function (Blueprint $table) {
$table->json('gallery')->nullable();
});
Register in Filament Resource
Use the GalleryJsonMedia trait in your Filament resource:
use Webplusm\GalleryJsonMedia\Traits\HasGalleryJsonMedia;
class YourResource extends Resource {
use HasGalleryJsonMedia;
// ...
}
First Use Case: Displaying Media Use the provided Blade component in your view:
@galleryJsonMedia('gallery')
Adding Media:
Use the GalleryJsonMedia field in your Filament form:
use Webplusm\GalleryJsonMedia\Fields\GalleryJsonMedia;
public static function form(Form $form): array {
return [
GalleryJsonMedia::make('gallery')
->label('Media Gallery')
->required(),
];
}
Fluent API for Media Manipulation:
// Add a single image
$model->gallery()->addImage('path/to/image.jpg', ['alt' => 'Description']);
// Add multiple images
$model->gallery()->addImages([
'path/to/image1.jpg',
'path/to/image2.jpg',
]);
// Add a document
$model->gallery()->addDocument('path/to/document.pdf', ['title' => 'Document']);
Basic Gallery Display:
@galleryJsonMedia('gallery')
Renders all images and documents in a responsive grid.
Customizing Display:
@galleryJsonMedia('gallery', [
'showDocuments' => false, // Hide documents
'imageClass' => 'w-1/3', // Custom CSS class for images
])
Adding Metadata:
$model->gallery()->addImage('image.jpg', [
'alt' => 'Custom Alt Text',
'position' => 1, // Order in gallery
'tags' => ['tag1', 'tag2'],
]);
Retrieving Metadata:
$images = $model->gallery->images;
foreach ($images as $image) {
echo $image->alt; // Access custom properties
}
Fluent API for API Responses:
return response()->json([
'gallery' => $model->gallery->toArray(),
]);
Filtering in API:
Use the GalleryJsonMedia query builder methods:
$model->gallery()->where('alt', 'like', '%description%');
Resource-Level Integration:
Ensure your resource extends Filament\Resources\Resource and includes the trait:
class PostResource extends Resource {
use HasGalleryJsonMedia;
// ...
}
Widget Integration: Create a custom widget to display galleries:
class GalleryWidget extends Widget {
public function getView(): string {
return view('widgets.gallery', [
'gallery' => $this->getGalleryData(),
]);
}
}
ToSearchableArray method in your model:
public function toSearchableArray(): array {
return [
'gallery' => $this->gallery->images->pluck('alt'),
];
}
config/gallery-json-media.php:
'storage' => [
'disk' => 'public',
'path' => 'galleries',
],
public static function getBulkActions(): array {
return [
Actions\DeleteBulkGalleryAction::make(),
];
}
Issue: MySQL JSON column may throw errors if data is malformed. Fix: Validate the JSON structure before saving:
$model->gallery = json_encode($model->gallery);
Tip: Use ->nullable() on the JSON column to avoid strict validation.
Issue: Large files may exceed PHP upload limits.
Fix: Adjust php.ini or use chunked uploads:
ini_set('post_max_size', '256M');
ini_set('upload_max_filesize', '256M');
Tip: Use Symfony\Component\HttpFoundation\File\UploadedFile for manual handling.
public function getGalleryAttribute($value) {
return cache()->remember("gallery_{$this->id}", now()->addHours(1), function() use ($value) {
return json_decode($value, true);
});
}
Schema::table('your_table', function (Blueprint $table) {
$table->json('gallery')->nullable()->after('other_column');
});
GalleryJsonMedia field may conflict with other Filament fields.
Fix: Use unique namespacing:
GalleryJsonMedia::make('custom.gallery')
->label('Custom Gallery')
public static function getDefaultGallery(): array {
return [
'images' => [],
'documents' => [],
];
}
php artisan vendor:publish --tag="gallery-json-media-views"
Then override in resources/views/vendor/gallery-json-media/.GalleryJsonMedia class to modify API responses:
class CustomGalleryJsonMedia extends GalleryJsonMedia {
public function toArray(): array {
return [
'images' => array_map(fn($image) => [
'url' => $image->url,
'thumbnail' => $this->getThumbnailUrl($image->url),
], $this->images),
];
}
}
class VideoGalleryJsonMedia extends GalleryJsonMedia {
public function addVideo(string $url, array $metadata = []): self {
$this->videos[] = [
'url' => $url,
...$metadata,
];
return $this;
}
}
namespace App\Services;
use Webplusm\GalleryJsonMedia\Contracts\StorageDriver;
class S3StorageDriver implements StorageDriver {
public function store($file, $path) {
// Custom S3 logic
}
}
Register in config:
'storage_driver' => \App\Services\S3StorageDriver::class,
class GalleryUpdatedListener {
public function handle($event) {
// Log or process gallery updates
}
}
Register in EventServiceProvider:
protected $listen = [
\Webplusm\GalleryJsonMedia\Events\GalleryUpdated::class => [
GalleryUpdatedListener::class,
],
];
use Webplusm\GalleryJsonMedia\Rules\ValidGallery;
public function rules(): array {
return [
'gallery' => ['required', new ValidGallery],
];
}
How can I help you explore Laravel packages today?