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

Media Bundle Laravel Package

akuma/media-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the bundle to your composer.json:

    composer require akuma/media-bundle
    

    Register the bundle in config/bundles.php:

    return [
        // ...
        Akuma\MediaBundle\AkumaMediaBundle::class => ['all' => true],
    ];
    
  2. Configuration Publish the default config:

    php artisan vendor:publish --tag=akuma-media-config
    

    Update config/akuma_media.php with your storage paths (e.g., public/media, private/media).

  3. First Use Case: Uploading Media Inject the Akuma\MediaBundle\Service\MediaService into a controller:

    use Akuma\MediaBundle\Service\MediaService;
    
    class MediaController extends Controller
    {
        protected $mediaService;
    
        public function __construct(MediaService $mediaService)
        {
            $this->mediaService = $mediaService;
        }
    
        public function upload(Request $request)
        {
            $file = $request->file('media');
            $media = $this->mediaService->upload($file, 'public'); // 'public' or 'private'
            return response()->json(['url' => $media->getUrl()]);
        }
    }
    
  4. Routes & Views Define a route in routes/web.php:

    Route::post('/upload', [MediaController::class, 'upload']);
    

    Use the media helper in Blade:

    <img src="{{ media('public', $media->getFilename()) }}" alt="Media">
    

Implementation Patterns

Core Workflows

  1. File Handling

    • Uploading: Use MediaService::upload($file, $storageType) to store files in either public or private storage.
    • Deleting: Delete media via MediaService::delete($mediaId).
    • Retrieving: Fetch media metadata with MediaService::find($mediaId).
  2. Storage Integration

    • Supports both public (web-accessible) and private (non-web-accessible) storage.
    • Configure paths in config/akuma_media.php:
      'storages' => [
          'public' => [
              'path' => 'public/media',
              'url'  => '/media',
          ],
          'private' => [
              'path' => 'private/media',
          ],
      ],
      
  3. Model Integration

    • Attach media to Eloquent models via a hasMany relationship:
      use Akuma\MediaBundle\Entity\Media;
      
      class Post extends Model
      {
          public function media()
          {
              return $this->hasMany(Media::class);
          }
      }
      
    • Use MediaService::attach($mediaId, $model) to link media to models.
  4. Validation

    • Validate file types/sizes in controllers:
      $request->validate([
          'media' => 'required|file|mimes:jpg,png|max:2048',
      ]);
      
  5. Batch Operations

    • Delete multiple media items:
      $this->mediaService->deleteMany([$id1, $id2]);
      

Integration Tips

  • Symfony Events: Extend functionality by listening to media.uploaded or media.deleted events.
  • Custom Storage: Override storage logic by implementing Akuma\MediaBundle\Storage\StorageInterface.
  • APIs: Return media URLs in JSON responses:
    return response()->json([
        'data' => $media->getUrl(),
        'thumbnail' => $media->getThumbnailUrl(),
    ]);
    

Gotchas and Tips

Pitfalls

  1. Storage Permissions

    • Ensure public/media and private/media directories are writable:
      chmod -R 775 storage/app/public/media
      chmod -R 775 storage/app/private/media
      
    • Fix: Run php artisan storage:link if using public/media symlinks.
  2. Missing Config

    • If media URLs return 404, verify config/akuma_media.php paths and storage:link.
  3. Private Storage Access

    • Private media cannot be accessed via URLs. Use MediaService::getStream() for direct responses:
      return response()->streamDownload(function () use ($media) {
          echo $media->getStream();
      }, $media->getFilename());
      
  4. Dependency on Core Bundle

    • Requires akuma/core-bundle (dev-master). Pin versions in composer.json to avoid instability:
      "akuma/core-bundle": "dev-master#1234abc"
      

Debugging

  • Log Uploads: Enable debug mode in config/akuma_media.php:
    'debug' => env('APP_DEBUG', false),
    
  • Check Events: Listen for media.error events to catch upload failures:
    Event::listen('media.error', function ($event) {
        Log::error('Media error: ' . $event->getMessage());
    });
    

Extension Points

  1. Custom Storage Drivers Override Akuma\MediaBundle\Storage\FilesystemStorage for S3/Cloud storage:

    class CustomStorage implements StorageInterface
    {
        public function save($file, $path)
        {
            // Custom logic (e.g., AWS S3)
        }
    }
    

    Register in config/akuma_media.php:

    'storage_driver' => \App\Storage\CustomStorage::class,
    
  2. Media Events Extend core events (e.g., media.uploaded) in EventSubscriber:

    class MediaSubscriber implements EventSubscriber
    {
        public static function getSubscribedEvents()
        {
            return [
                'media.uploaded' => 'onMediaUploaded',
            ];
        }
    
        public function onMediaUploaded(MediaEvent $event)
        {
            // Post-upload logic (e.g., generate thumbnails)
        }
    }
    
  3. Validation Rules Add custom rules to config/akuma_media.php:

    'validation' => [
        'mimes' => ['jpg', 'png', 'pdf'],
        'max_size' => '5120', // KB
    ],
    

Pro Tips

  • Thumbnails: Use MediaService::generateThumbnail() for on-the-fly resizing:
    $thumbnail = $this->mediaService->generateThumbnail($mediaId, 200, 200);
    
  • Model Observers: Auto-delete media when models are deleted:
    class PostObserver
    {
        public function deleting(Post $post)
        {
            $post->media()->each(function ($media) {
                app(MediaService::class)->delete($media->id);
            });
        }
    }
    
  • Caching: Cache media metadata in Redis for high-traffic apps:
    $media = app(MediaService::class)->find($id, ['cache' => true]);
    
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