Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Attachmentable Laravel Package

laravelir/attachmentable

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require laravelir/attachmentable
    php artisan attachmentable:install
    php artisan migrate
    

    Ensure AttachmentableServiceProvider is registered in config/app.php.

  2. Basic Setup:

    • Add Attachmentable trait to models needing attachments (e.g., Post).
    • Add Attachmentorable trait to models that own attachments (e.g., User).
  3. First Use Case: Attach a file to a Post owned by a User:

    $user = User::find(1);
    $post = $user->posts()->create(['title' => 'My Post']);
    
    $post->attachFile('path/to/file.pdf', 'document'); // 'document' is the attachment type
    

Where to Look First

  • Configuration: config/attachmentable.php (disk, validation rules, etc.).
  • Migrations: Check database/migrations/ for attachmentable tables.
  • Traits: Review Attachmentable and Attachmentorable methods in Traits/.

Implementation Patterns

Core Workflows

  1. Attaching Files:

    // Single file
    $model->attachFile($filePath, $type, ['custom' => 'metadata']);
    
    // Multiple files (array of paths)
    $model->attachFiles(['path1.jpg', 'path2.jpg'], 'images');
    
  2. Retrieving Attachments:

    // Get all attachments for a model
    $attachments = $model->attachments;
    
    // Get by type
    $documents = $model->attachments->where('type', 'document');
    
    // Get URL of a specific attachment
    $url = $model->attachments->first()->url;
    
  3. Deleting Attachments:

    $model->detachFile($attachmentId); // By ID
    $model->detachFiles(['type' => 'images']); // By type/query
    $model->detachAllFiles(); // All attachments
    

Integration Tips

  • Validation: Extend config/attachmentable.php to customize allowed file types/sizes:
    'validation' => [
        'types' => ['document' => ['pdf', 'doc'], 'image' => ['jpg', 'png']],
        'max_size' => 10240, // 10MB
    ],
    
  • Events: Listen for attachment.attached/attachment.detached:
    event(new AttachmentAttached($model, $attachment));
    
  • Polymorphic Ownership: Use Attachmentorable on models like User, Project, etc., to centralize attachment management.

Advanced Patterns

  • Custom Storage: Override the default disk by publishing config:
    php artisan vendor:publish --provider="Laravelir\Attachmentable\Providers\AttachmentableServiceProvider"
    
    Then update config/attachmentable.php:
    'disk' => 's3',
    
  • Soft Deletes: Enable soft deletes for attachments:
    use Laravelir\Attachmentable\Traits\SoftDeletesAttachment;
    
    class Post extends Model {
        use SoftDeletesAttachment;
    }
    

Gotchas and Tips

Pitfalls

  1. Ownership Confusion:

    • Ensure Attachmentorable is on the owner model (e.g., User), not the attachment target (e.g., Post).
    • Fix: Double-check trait placement; attachments belong to owners, not models.
  2. File Path Handling:

    • Paths must be absolute or resolvable via Laravel’s filesystem. Relative paths may fail silently.
    • Fix: Use storage_path('app/uploads/file.pdf') or public_path('uploads/file.pdf').
  3. Migration Conflicts:

    • If attachmentable:install fails, manually check for duplicate attachments table migrations.
    • Fix: Rollback and re-run migrations or adjust table names in config.
  4. Disk Permissions:

    • Attachments stored on local disks may fail if permissions are restrictive.
    • Fix: Ensure the storage directory is writable:
      chmod -R 775 storage/app/public
      

Debugging

  • Attachment Not Found:

    • Verify the attachable_id and attachable_type in the attachments table match the owner model’s primary key and class name.
    • Query:
      \DB::table('attachments')->where('attachable_id', $user->id)->where('attachable_type', 'App\Models\User')->get();
      
  • File Not Uploaded:

    • Check the disk config and ensure the file exists at the specified path.
    • Log:
      \Log::debug('Attachment path:', [$filePath, config('attachmentable.disk')]);
      

Extension Points

  1. Custom Attachment Model:

    • Publish the migration and extend the Attachment model:
      php artisan vendor:publish --tag=attachmentable-migrations
      
    • Add fields (e.g., mime_type, size) to the attachments table.
  2. Custom Storage Logic:

    • Override the storeFile method in a service class:
      namespace App\Services;
      
      use Laravelir\Attachmentable\Attachment;
      
      class CustomAttachmentService {
          public function storeFile(Attachment $attachment, $filePath) {
              // Custom logic (e.g., rename files, process before storage)
              return $attachment->store($filePath);
          }
      }
      
    • Bind the service in AttachmentableServiceProvider.
  3. API Responses:

    • Use accessors to format attachment data for APIs:
      public function getAttachmentUrlAttribute() {
          return $this->url . '?t=' . time(); // Cache-busting
      }
      

Pro Tips

  • Batch Processing: Use chunk() for large attachment operations to avoid memory issues:

    $user->posts()->chunk(100, function ($posts) {
        foreach ($posts as $post) {
            $post->attachFiles([...], 'images');
        }
    });
    
  • Testing: Mock the filesystem in tests:

    $this->partialMock(\Illuminate\Filesystem\Filesystem::class, function ($mock) {
        $mock->shouldReceive('exists')->andReturnTrue();
        $mock->shouldReceive('put')->andReturnTrue();
    });
    
  • Performance:

    • Index attachable_id and attachable_type in the attachments table for large datasets.
    • Use with() to eager-load attachments:
      $user->load('attachments');
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui