raise-studio / filament-media-library
Decoupled, independently publishable Filament media library plugin: central media + reusable picker + folders + tags + multi-disk/OSS + multi-tenancy + content dedup + rich-text insertion.
Package info
github.com/raise-studio/filament-media-library
pkg:composer/raise-studio/filament-media-library
Requires
- php: ^8.2
- filament/filament: ^4
- illuminate/contracts: ^11.0 || ^12.0
Requires (Dev)
- orchestra/testbench: ^10.0
- phpunit/phpunit: ^11.5
Suggests
- bezhansalleh/filament-shield: Optional; enable use_shield=true to let Filament Shield manage permissions (avoids dual-policy conflicts).
This package is auto-updated.
Last update: 2026-08-12 14:06:49 UTC
README
🌐 Other languages: 中文
Decoupled, independently publishable Filament 4 media library: a central media store + reusable picker (MediaPicker) + folders + tags + multi-disk / OSS + multi-tenancy + content dedup + rich-text insertion.
How it differs from
spatie/laravel-medialibrary: This package does not provide theInteractsWithMedia"attach media to a model" pattern. Instead it offers a central media library + popup picker. A form field only persists themedia_id(or an array of ids); the actual files live in a centralmediatable, which makes dedup, cross-module reference tracking, and unified disk/tenant management straightforward. The two packages don't conflict and can coexist.
Requirements
- PHP
^8.2 - Laravel
11or12 - Filament
^4
Installation
composer require raise-studio/filament-media-library
Migrations are loaded automatically. To customize the table prefix / disk / language files, publish the assets:
php artisan vendor:publish --tag=media-library-config php artisan vendor:publish --tag=media-library-views php artisan vendor:publish --tag=media-library-translations
Panel registration
Attach the plugin in any Filament panel (the picker's views / upload routes / migrations depend on it, so registration is required):
use RaiseStudio\FilamentMediaLibrary\FilamentMediaLibraryPlugin; public function panel(Panel $panel): Panel { return $panel // ... ->plugin(FilamentMediaLibraryPlugin::make()); }
The plugin auto-registers MediaLibraryResource (the media management admin).
Using MediaPicker in your forms
MediaPicker is a standard Filament Field subclass and works directly without any panel registration:
use RaiseStudio\FilamentMediaLibrary\Filament\Forms\Components\MediaPicker; use Filament\Schemas\Schema; public static function form(Schema $schema): Schema { return $schema->components([ MediaPicker::make('avatar') ->multiple(false) ->defaultFilterMode('image'), // 'all' | 'image' | 'file' MediaPicker::make('attachments') ->multiple() ->defaultFilterMode('file'), ]); }
The field only persists media_id (single value) or an array of ids (multiple); the write-back is pushed to Livewire via Alpine $entangle.
forge users may use the thinner wrapper
RaiseStudio\FilamentForge\Fields\ForgeMediaField::avatar()/image()/file(), which falls back to the nativeFileUploadwhen this package is not installed.
Configuration
Key entries in config/media-library.php (overridable after publishing):
| Key | Default | Description |
|---|---|---|
table_prefix |
'' |
Table prefix. Recommended: set something like rs_ to avoid colliding with spatie/laravel-medialibrary's media table. |
media_disk |
public |
Write disk; switch to OSS/COS/S3 by registering the disk in the host and setting MEDIA_LIBRARY_DISK. |
user_model |
App\Models\User::class |
Uploader model (dedup ownership created_by). |
register_navigation |
true |
Ships its own navigation when used standalone; set false for forge integration. |
tenant_resolver |
NullTenantResolver |
Multi-tenancy resolver contract implementation; use NullTenantResolver for single-tenant. |
use_shield |
null |
Leave empty = auto-detect: if Filament Shield is installed, defer to Shield; otherwise register the built-in Policy for self-protection. |
dedup |
true |
Reuse by sha256; if it already exists, don't write again. |
allowed_mimes |
images / docs / archives / av | Upload allowlist (no executables). |
Multi-tenancy
Implement the RaiseStudio\FilamentMediaLibrary\Tenancy\ResolvesTenant contract and reference it in config:
'tenant_resolver' => App\Tenancy\MyTenantResolver::class,
The resolver returns the current tenant_id and the super-admin check; media paths automatically get a t-{id}/ prefix (disk-agnostic).
OSS / Object storage
This package is not bound to any S3/OSS/COS adapter. After registering the corresponding disk in the host config/filesystems.php, set MEDIA_LIBRARY_DISK=oss to switch everything over; the library's disk reads and URL generation all go through the Laravel Storage abstraction transparently. See docs/oss-storage-integration.md for details.
Security
- The upload endpoint
POST /media-library/uploadis protected by theauthmiddleware; anonymous uploads are rejected (401 if not logged in). - Uploads are validated against the
allowed_mimesallowlist viamimes; executables are excluded by default. - When
use_shieldis left empty it auto-detects Shield; if Shield is not installed, the built-inMediaPolicyis registered so the media model is always authorized.
Testing
vendor/bin/pest
License
MIT © RaiseStudio