zeeshantariq/filament-attachmate
Publish Migrations & Config
Run the publisher command to set up the attachments table and default configuration:
php artisan vendor:publish --provider="Zeeshantariq\FilamentAttachmate\FilamentAttachmateServiceProvider" --tag="migrations"
php artisan vendor:publish --provider="Zeeshantariq\FilamentAttachmate\FilamentAttachmateServiceProvider" --tag="config"
Then migrate:
php artisan migrate
Define a Polymorphic Attachment Model
Extend the Attachment model (auto-generated by the migration) in your App\Models:
use Zeeshantariq\FilamentAttachmate\Models\Attachment;
class AppAttachment extends Attachment {}
First Use Case: Attach Files to a Model
Add the HasAttachments trait to your Filament resource model:
use Zeeshantariq\FilamentAttachmate\Traits\HasAttachments;
class Post extends Model
{
use HasAttachments;
}
Then register the attachment panel in your Filament resource:
public static function form(Form $form): Form
{
return $form
->schema([
// ... other fields
Attachmate::make('attachments')
->label('Attachments')
->maxAttachments(10),
]);
}
Polymorphic Attachment Management
Attachmate::make() in Filament forms/tables to render attachment panels.Attachmate::make('attachments')
->label('Media')
->accept(['image/*', 'application/pdf'])
->maxAttachments(5)
->thumbnailWidth(100)
Integration with Filament Resources
use Zeeshantariq\FilamentAttachmate\Columns\AttachmentsCountColumn;
Table::column(AttachmentsCountColumn::make())
Custom Storage & Validation
Attachment model:
protected static function boot()
{
parent::boot();
static::creating(function ($attachment) {
$attachment->disk = 's3';
});
}
Attachmate panel:
Attachmate::make()
->rules(['attachments.*' => 'mimes:jpeg,png|max:2048'])
Bulk Operations
attachments relationship in queries:
$post = Post::with('attachments')->find(1);
$post->attachments()->delete(); // Bulk delete
API & External Access
Attachment model directly in APIs or services:
$attachments = Auth::user()->attachments()->latest()->get();
Dynamic Attachment Limits
maxAttachments based on user roles or model state:
Attachmate::make()
->maxAttachments(fn ($record) => $record->isPremium() ? 20 : 5)
Custom Attachment Models
Attachment model to add metadata:
class CustomAttachment extends Attachment
{
protected $casts = [
'alt_text' => 'string',
];
}
HasAttachments trait to use your model:
use Zeeshantariq\FilamentAttachmate\Traits\HasAttachments as BaseHasAttachments;
trait HasAttachments extends BaseHasAttachments
{
public function attachments()
{
return $this->morphMany(CustomAttachment::class, 'attachable');
}
}
Event Listeners
AttachmentCreated):
use Zeeshantariq\FilamentAttachmate\Events\AttachmentCreated;
AttachmentCreated::listen(function ($attachment) {
// Send notification, log, etc.
});
Filament Notifications
use Filament\Notifications\Notification;
Attachmate::make()
->afterAttach(function ($record, $attachments) {
Notification::make()
->title('Attachments added')
->success()
->send();
});
Migration Conflicts
attachments table, reset it via:
php artisan migrate:fresh --env=testing
--env=testing to avoid production data loss.Polymorphic Key Mismatches
getRouteKeyName() matches the polymorphic key used in queries:
public function getRouteKeyName()
{
return 'slug'; // Must match the column used in `attachments` table
}
File Upload Limits
upload_max_filesize and post_max_size may block large uploads. Adjust in php.ini or use chunked uploads:
Attachmate::make()
->chunkUploads(true)
->chunkSize(5) // MB
Caching Issues
php artisan filament:cache:clear
Permission Denied Errors
attachments table’s attachable_id/attachable_type columns are indexed:
Schema::table('attachments', function (Blueprint $table) {
$table->index(['attachable_id', 'attachable_type']);
});
Log Upload Paths
Attachment model:
protected static function boot()
{
static::created(function ($attachment) {
\Log::debug('Attachment stored at:', [$attachment->path]);
});
}
Validate Disk Configuration
config/filesystems.php for correct disk settings (e.g., local, s3):
'disks' => [
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
// ...
],
],
Test Polymorphic Relationships
$post = Post::find(1);
$post->attachments()->count(); // Should return > 0
Check Filament Logs
config/filament.php:
'debug' => env('FILAMENT_DEBUG', false),
storage/logs/filament.log.Custom Storage Drivers
Attachment model:
use Illuminate\Support\Facades\Storage;
class CustomAttachment extends Attachment
{
public function getPathAttribute($value)
{
return 'custom/' . parent::getPathAttribute($value);
}
}
Add Metadata Fields
attachments table and model:
Schema::table('attachments', function (Blueprint $table) {
$table->string('alt_text')->nullable();
$table->unsignedTinyInteger('priority')->default(1);
});
Then update the Attachment model’s $fillable.Override UI Components
php artisan vendor:publish --tag="filament-attachmate-views"
resources/views/vendor/filament-attachmate/....Add Custom Actions
use Zeeshantariq\FilamentAttachmate\Actions\DownloadAttachment;
Table::column(AttachmentsColumn::make())
->actions([
DownloadAttachment::make(),
Action::make('share')
->url(fn ($record) => route('attachments.share', $record))
->icon('heroicon-o-share'),
]);
Integrate with Filament Spatie Media Library
$post->attachments()->each(fn ($
How can I help you explore Laravel packages today?