Laravel-Mediable

repository·master·Indexed 21 days ago

https://github.com/plank/laravel-mediable

A Laravel package for uploading and attaching media files to Eloquent models using polymorphic relationships and a tagging system. It features a fluent API for uploads, support for multiple filesystem disks, media validation, and Artisan commands for importing, pruning, and syncing media records. It also integrates with intervention/image for creating media variants and provides utilities for generating public, temporary, or streamed URLs.

Tokens
23.2K
Snippets
87
Records
98
Agent score
72%

What's inside laravel-mediable

  1. Overview of Laravel-Mediable features

    master

    Laravel-Mediable is a package designed for uploading and attaching media files to Laravel models. Key capabilities include:

    • Filesystem-driven approach: Configurable upload directories with varying accessibility levels. You can restrict uploads using MIME types, file extensions, or aggregate types (e.g., using image to cover JPEG, PNG, and GIF).
    • Polymorphic relationships: Uses many-to-many polymorphic relationships, allowing you to attach any number of media files to any number of models without modifying your existing database schema.
    • Tagging system: Allows attaching media to models using tags to categorize their purpose, such as thumbnail, featured image, gallery, or download.
    • Image manipulation: Integrated support for intervention/image to create media variants (e.g., different sizes or formats) for specific use cases.
  2. Define custom Aggregate Types

    master

    Aggregate types allow you to group multiple MIME types and extensions under a single identifier. This makes it easier to manage and find similar media (e.g., all forms of 'markup'). Each Media record can only belong to one aggregate type. You can add or modify these in config/mediable.php under the aggregate_types key.

    'aggregate_types' => [
        'markup' => [
            'mime_types' => [
                'text/markdown',
                'text/html',
                'text/xml',
                'application/xml',
                'application/xhtml+xml',
            ],
            'extensions' => [
                'md',
                'html',
                'htm',
                'xhtml',
                'xml'
            ]
        ],
    ]
  3. How media tagging and retrieval works

    master

    The package uses many-to-many polymorphic relationships to allow media to be assigned to any model without schema changes. You can use tags to categorize media for specific purposes (e.g., 'thumbnail', 'featured image', 'gallery', or 'download').

    When you call attachMedia($media, ['tag_name']), you are creating a relationship between the model and the media record under that specific tag. You can then use getMedia('tag_name') to retrieve only the media associated with that purpose.

  4. Configure automatic media rehydration

    master

    By default, Mediable models automatically reload their media relationship if a tag is modified (marked as 'dirty') and then accessed. This ensures that methods like getMedia() return the most current data.

    To disable this behavior, set the $rehydrates_media property to false on your model. You can also control the global default in config/mediable.php using the rehydrate_media key.

    class Post extends Model
    {
        use Mediable;
    
        protected $rehydrates_media = false;
    }
  5. How aggregate types work

    master
    An aggregate type is an abstraction that groups multiple specific file formats (MIME types or extensions) under a single identifier. Instead of managing logic for image/jpeg, image/png, and image/gif separately, you can interact with the single Media::TYPE_IMAGE aggregate type. This simplifies both querying existing media and validating new uploads.
  6. Upload files using MediaUploader

    master

    The MediaUploader class (accessed via the MediaUploader Facade) is the primary way to upload media. It handles file validation, moving the file to the destination, and creating a Media record.

    To perform a basic upload to the default disk configured in config/mediable.php:

    use MediaUploader;
    $media = MediaUploader::fromSource($request->file('thumbnail'))->upload();
    <?php
    use MediaUploader; //use the facade
    $media = MediaUploader::fromSource($request->file('thumbnail'))->upload();
  7. Handle MediaUploadException with granular HTTP status codes

    master

    By default, Plank\Mediable\MediaUploadException might result in a 500 error. To return appropriate HTTP status codes (e.g., 413 for file size issues), use the Plank\Mediable\HandlesMediaUploadExceptions trait in your Exceptions\Handler or your Controller.

    In the Exception Handler, call $this->transformMediaUploadException($e) within the render method.

    <?php
    // In Exception Handler
    namespace App\Exceptions;
    
    use Plank\Mediable\HandlesMediaUploadExceptions;
    
    class Handler
    {
        use HandlesMediaUploadExceptions;
    
        public function render($request, $e)
        {
            $e = $this->transformMediaUploadException($e);
            return parent::render($request, $e);
        }
    }
    
    // OR in a Controller
    class ExampleController extends Controller
    {
        use HandlesMediaUploadExceptions;
    
        public function upload(Request $request)
        {
            try {
                MediaUploader::fromSource($request->file('file'))
                    ->upload();
            } catch (MediaUploadException $e) {
                throw $this->transformMediaUploadException($e);
            }
        }
    }
  8. Publish configuration and run migrations

    master

    After installation, publish the package configuration file to config/mediable.php and run the database migrations to create the necessary tables.

    php artisan vendor:publish --provider="Plank\Mediable\MediableServiceProvider"
    php artisan migrate
  9. Use and navigate Media variants

    master

    Variants are fully functional Media records that act as derivatives of an 'original' file. They can be attached to Mediable models, have output paths/URLs, and be moved or copied.

    You can access a specific variant from a media collection using findVariant('variant_name') to retrieve its URL or other properties.

    Note: To avoid unnecessary database calls, avoid chaining find calls (e.g., $media->findVariant()->findOriginal()). Instead, always start from a single initial node.

    <?php
    $src = $post->getMedia('feature')
        ->findVariant('thumbnail')
        ->getUrl();
  10. Configure Intervention/image ImageManager

    master

    Laravel-Mediable uses the intervention/image library for image manipulation. While the package attempts to automatically select a driver (imagick preferred, falling back to gd), you can manually configure the bindings in your Laravel service container.

    For Intervention/image >= 3.0

    Recommended: Install intervention/image-laravel to handle container bindings automatically.

    Manual Binding: Add the following to your AppServiceProvider:

    class AppServiceProvider extends ServiceProvider
    {
        public function register()
        {
            // if using GD
            $this->app->bind(Intervention\Image\Interfaces\DriverInterface::class,
                \Intervention\Image\Drivers\Gd\Driver::class
            );
    
            // if using Imagick
            $this->app->bind(Intervention\Image\Interfaces\DriverInterface::class,
                \Intervention\Image\Drivers\Imagick\Driver::class
            );
        }
    }

    For Intervention/image < 3.0

    Recommended: Follow the official Intervention/image guide to enable the Laravel service provider.

    Manual Binding:

    use Intervention\Image\ImageManager;
    
    class AppServiceProvider extends ServiceProvider
    {
        public function register()
        {
            $this->app->bind(
                ImageManager::class,
                function() {
                    return new ImageManager(['driver' => 'imagick']);
                    // return new ImageManager(['driver' => 'gd']);
                }
            );
        }
    }
    <?php
    class AppServiceProvider extends ServiceProvider
    {
        public function register()
        {
            // if using GD
            $this->app->bind(Intervention\Image\Interfaces\DriverInterface::class,
                \Intervention\Image\Drivers\Gd\Driver::class
            );
    
            // if using Imagick
            $this->app->bind(Intervention\Image\Interfaces\DriverInterface::class,
                \Intervention\Image\Drivers\Imagick\Driver::class
            );
        }
    }
  11. Enable media handling on Eloquent models

    master

    To allow an Eloquent model to have media attached to it, implement the Plank\Mediable\MediableInterface interface and use the Plank\Mediable\Mediable trait within your class.

    <?php
    
    namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    use Plank\Mediable\Mediable;
    use Plank\Mediable\MediableInterface;
    
    class Post extends Model implements MediableInterface
    {
        use Mediable;
    
        // ...
    }