PHPackages                             carone/laravel-media - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Image &amp; Media](/categories/media)
4. /
5. carone/laravel-media

ActiveLibrary[Image &amp; Media](/categories/media)

carone/laravel-media
====================

Adds media functionality to laravel apps

1.2(3mo ago)09MITPHPPHP ^8.2CI passing

Since Nov 28Pushed 3mo agoCompare

[ Source](https://github.com/EmileCar/laravel-media)[ Packagist](https://packagist.org/packages/carone/laravel-media)[ RSS](/packages/carone-laravel-media/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (3)Dependencies (8)Versions (5)Used By (0)

\# Carone Laravel Media Package
===============================

[](#-carone-laravel-media-package)

A comprehensive media management package for Laravel applications that provides a clean, facade-based API for handling various media types including images, videos, audio files, and documents.

Installation
------------

[](#installation)

Install the package via Composer:

```
composer require carone/laravel-media
```

Publish the configuration file:

```
php artisan vendor:publish --provider="Carone\Media\CaroneMediaServiceProvider" --tag="config"
```

Run the migrations:

```
php artisan migrate
```

Admin Panel
-----------

[](#admin-panel)

The package includes a beautiful admin interface for managing media files. Access it at `/admin/media` (configurable).

### Features

[](#features)

- 📸 **Visual Media Browser** - Grid view with thumbnails for all media types
- 🔍 **Advanced Filtering** - Filter by type, source, tags, and search by name/description
- 🏷️ **Tag Management** - Add, edit, and remove tags from media
- ✏️ **Quick Edit** - Update media name, description, and tags inline
- 🗑️ **Bulk Actions** - Select multiple media and delete in bulk
- 📊 **Statistics** - View media counts by type and source
- 📱 **Responsive Design** - Works seamlessly on all devices

### Configuration

[](#configuration)

Configure the admin panel in `config/media.php`:

```
'admin' => [
    'enabled' => true,
    'route_prefix' => 'admin/media', // Customize the admin URL
],
```

### Access Control

[](#access-control)

The admin panel is protected by the `management_middleware` configuration:

```
'management_middleware' => ['auth'], // Require authentication
// or
'management_middleware' => ['auth', 'admin'], // Require admin role
```

⚠️ IMPORTANT: Public API
------------------------

[](#️-important-public-api)

**This package provides ONLY ONE public interface: the `Media` facade.**

External projects should **NEVER** directly access internal classes like:

- ❌ `Carone\Media\Services\*`
- ❌ `Carone\Media\Strategies\*`
- ❌ `Carone\Media\Models\*`
- ❌ `Carone\Media\Contracts\*`

**Always use the facade:**

- ✅ `Carone\Media\Facades\Media`

Basic Usage
-----------

[](#basic-usage)

All media operations are performed through the `Media` facade:

```
use Carone\Media\Facades\Media;

// Store a new media file with tags
$media = Media::store([
    'file' => $uploadedFile,
    'name' => 'My Image',
    'description' => 'A beautiful landscape photo',
    'type' => 'image',
    'tags' => ['Nature', 'Photography', 'Landscape'], // Optional tags
]);

// Get media by ID
$media = Media::getById(1);

// Get media by type with pagination
$result = Media::getByType('image', limit: 10, offset: 0);

// Search media
$result = Media::search('landscape', type: 'image', limit: 5);

// Serve media file
return Media::serve('image', 'filename.jpg');

// Serve thumbnail
return Media::thumbnail('image', 'filename.jpg');

// Delete media
Media::delete(1);

// Delete multiple media files
$result = Media::deleteMultiple([1, 2, 3]);

// Delete all media of a specific type
$result = Media::deleteByType('image');

// Clean up orphaned files
$result = Media::cleanupOrphanedFiles('image');

// Get enabled media types
$types = Media::getEnabledTypes();
```

Configuration
-------------

[](#configuration-1)

Configure media types and settings in `config/media.php`:

```
return [
    'enabled_types' => [
        'image' => [
            'enabled' => true,
            'max_file_size' => 10240, // KB
            'allowed_extensions' => ['jpg', 'jpeg', 'png', 'gif', 'webp'],
            'thumbnails' => [
                'enabled' => true,
                'width' => 300,
                'height' => 300,
            ],
        ],
        'video' => [
            'enabled' => true,
            'max_file_size' => 102400, // KB
            'allowed_extensions' => ['mp4', 'avi', 'mov', 'wmv'],
        ],
        // ... other types
    ],

    'storage' => [
        'disk' => 'public',
        'path' => 'media',
    ],

    'tags' => [
        'enabled' => true, // Enable/disable tagging system
    ],
];
```

Media Types
-----------

[](#media-types)

The package supports four media types:

- **Image**: JPEG, PNG, GIF, WebP with automatic thumbnail generation
- **Video**: MP4, AVI, MOV, WMV
- **Audio**: MP3, WAV, OGG, AAC
- **Document**: PDF, DOC, DOCX, TXT

Each type can be individually enabled/disabled in the configuration.

Tags
----

[](#tags)

The package includes a flexible tagging system that allows you to organize and categorize your media files.

### Uploading Media with Tags

[](#uploading-media-with-tags)

```
use Carone\Media\Facades\Media;

// Upload image with tags
$media = Media::store([
    'type' => 'image',
    'file' => $request->file('image'),
    'name' => 'Sunset Photo',
    'tags' => ['Nature', 'Photography', 'Sunset'], // Tags are automatically created if they don't exist
]);

// Upload external media with tags
$media = Media::store([
    'type' => 'video',
    'source' => 'external',
    'url' => 'https://youtube.com/watch?v=example',
    'name' => 'Tutorial Video',
    'tags' => ['Tutorial', 'Education'],
]);
```

### Managing Tags

[](#managing-tags)

Tags are automatically created if they don't exist. The package handles:

- **Automatic slug generation** - "Nature Photography" becomes "nature-photography"
- **Case-insensitive matching** - "Nature", "nature", and "NATURE" are treated as the same tag
- **Duplicate prevention** - Reuses existing tags instead of creating duplicates

### Accessing Tags

[](#accessing-tags)

```
// Get all tags for a media resource
$tags = $media->tags; // Collection of Tag models

// Get tag names
$tagNames = $media->tags->pluck('name')->toArray();
// ['Nature', 'Photography', 'Sunset']

// Get tag slugs
$tagSlugs = $media->tags->pluck('slug')->toArray();
// ['nature', 'photography', 'sunset']
```

### Updating Tags

[](#updating-tags)

```
// Sync tags (replaces existing tags)
$media->syncTags(['New Tag', 'Another Tag']);

// The old tags are removed, only the new ones remain
```

### Configuration

[](#configuration-2)

Enable or disable tags in `config/media.php`:

```
'tags' => [
    'enabled' => true, // Set to false to disable tagging functionality
],
```

When tags are disabled:

- Tags provided during upload are ignored
- Existing tag relationships remain in the database
- No validation errors are thrown

API Response Format
-------------------

[](#api-response-format)

### Public Search Endpoints (GET /api/media/search, GET /api/media/type/{type})

[](#public-search-endpoints-get-apimediasearch-get-apimediatypetype)

These public endpoints return a minimal, SEO-friendly format:

```
{
    "data": [
        {
            "id": 1,
            "name": "My Image",
            "description": "A beautiful landscape photo",
            "date": "2025-01-15",
            "type": "image",
            "thumbnail_url": "https://example.com/media/thumbnails/1",
            "media_url": "https://example.com/media/images/photo.jpg",
            "tags": [
                {"id": 1, "name": "Nature", "slug": "nature"},
                {"id": 2, "name": "Photography", "slug": "photography"}
            ]
        }
    ],
    "total": 50,
    "limit": 20,
    "offset": 0
}
```

**Public Response Fields:**

- `id` - Media resource ID (for detail pages, routing)
- `name` - Display name
- `description` - Optional description (for alt text, tooltips)
- `date` - ISO date string
- `type` - Media type (image, video, audio, document)
- `thumbnail_url` - Thumbnail URL (null if no thumbnail)
- `media_url` - Direct URL to media file
- `tags` - Array of tag objects with id, name, and slug

### Single Media Resource (GET /api/media/{id})

[](#single-media-resource-get-apimediaid)

The detail endpoint returns complete information:

```
{
    "id": 1,
    "name": "My Image",
    "description": "A beautiful landscape photo",
    "type": "image",
    "file_name": "image_20231025_123456.jpg",
    "file_size": 2048576,
    "mime_type": "image/jpeg",
    "source": "local",
    "path": "/storage/media/images/image_20231025_123456.jpg",
    "thumbnail_path": "/storage/media/images/thumbnails/image_20231025_123456.jpg",
    "meta_data": {
        "width": 1920,
        "height": 1080,
        "exif": {...}
    },
    "tags": [
        {"id": 1, "name": "Nature", "slug": "nature"},
        {"id": 2, "name": "Photography", "slug": "photography"}
    ],
    "created_at": "2023-10-25T12:34:56.000000Z",
    "updated_at": "2023-10-25T12:34:56.000000Z"
}
```

### Paginated Results

[](#paginated-results)

Public browsing and search endpoints return simplified data:

```
{
    "current_page": 1,
    "data": [
        {
            "id": 1,
            "name": "example.jpg",
            "description": "Example image",
            "date": "2024-01-01",
            "type": "image",
            "thumbnail_url": "http://localhost/media/thumbnails/1",
            "media_url": "http://localhost/media/uploads/2024/01/example.jpg",
            "tags": [
                {"id": 1, "name": "Nature", "slug": "nature"}
            ]
        }
    ],
    "per_page": 15,
    "total": 100
}
```

Management endpoints return complete resource data:

```
{
    "id": 1,
    "name": "example.jpg",
    "description": "Example image",
    "date": "2024-01-01",
    "type": "image",
    "file_extension": "jpg",
    "file_size": 1024000,
    "thumbnail_id": 1234,
    "metadata": {
        "dimensions": {"width": 1920, "height": 1080},
        "exif": {...}
    },
    "tags": [
        {"id": 1, "name": "Nature", "slug": "nature"}
    ],
    "created_at": "2024-01-01T12:00:00.000000Z",
    "updated_at": "2024-01-01T12:00:00.000000Z"
}
```

### Search Results

[](#search-results)

```
{
    "data": [...], // Array of media resources (format depends on endpoint)
    "total": 10,
    "offset": 0,
    "limit": 20,
    "query": "landscape",
    "type": "image"
}
```

Media Serving
-------------

[](#media-serving)

### Path-Based URLs

[](#path-based-urls)

Media files are served using clean, SEO-friendly path-based URLs:

```
GET /media/{path}

Examples:
- /media/images/2024/photo.jpg
- /media/documents/reports/annual-report.pdf
- /media/videos/demo.mp4

```

The path corresponds directly to the file's location in storage, making URLs predictable and clean.

### Thumbnails

[](#thumbnails)

Thumbnails are served by ID (since they can be on different disks):

```
GET /media/thumbnails/{id}

Example:
- /media/thumbnails/1

```

### URL Generation

[](#url-generation)

The public search endpoints automatically generate these URLs:

```
{
    "media_url": "https://example.com/media/images/photo.jpg",
    "thumbnail_url": "https://example.com/media/thumbnails/1"
}
```

Security
--------

[](#security)

- All file uploads are validated for type and size
- File extensions are strictly checked against allowed lists
- MIME type validation prevents malicious uploads
- Automatic cleanup of orphaned files
- Tag input is sanitized and validated

Error Handling
--------------

[](#error-handling)

The facade will throw appropriate exceptions:

```
try {
    $media = Media::store($data);
} catch (\InvalidArgumentException $e) {
    // Invalid media type or validation failed
} catch (\Exception $e) {
    // Other storage errors
}
```

Testing
-------

[](#testing)

Run the package tests:

```
composer test
```

Package Architecture (Internal)
-------------------------------

[](#package-architecture-internal)

> **⚠️ WARNING: The following information is for package development only.**
>
> **External projects should NEVER access these internal components directly.****Always use the Media facade.**

### Internal Structure

[](#internal-structure)

```
src/
├── Facades/
│   └── Media.php                    # ✅ PUBLIC API - Use this
├── MediaManager.php                 # ❌ INTERNAL - Do not use
├── CaroneMediaServiceProvider.php   # ❌ INTERNAL - Do not use
├── Contracts/                       # ❌ INTERNAL - Do not use
├── Services/                        # ❌ INTERNAL - Do not use
├── Strategies/                      # ❌ INTERNAL - Do not use
├── Models/                          # ❌ INTERNAL - Do not use
│   ├── MediaResource.php           # Media model
│   └── Tag.php                     # Tag model (for tagging system)
├── Enums/                          # ❌ INTERNAL - Do not use
└── Utilities/                      # ❌ INTERNAL - Do not use

```

### Key Internal Components

[](#key-internal-components)

- **MediaManager**: Central orchestrator (accessed via facade)
- **Services**: Business logic layer
- **Strategies**: Media type-specific processing
- **Models**: Database entities (MediaResource, Tag)
- **Contracts**: Service interfaces

Database Schema
---------------

[](#database-schema)

The package creates the following tables:

### media\_resources

[](#media_resources)

Stores all media files (images, videos, audio, documents)

### media\_tags

[](#media_tags)

Stores tags that can be attached to media resources

- `id` - Primary key
- `name` - Display name (e.g., "Nature Photography")
- `slug` - URL-friendly slug (e.g., "nature-photography")
- `created_at`, `updated_at` - Timestamps

### media\_resource\_tag

[](#media_resource_tag)

Pivot table for many-to-many relationship between media and tags

- `media_resource_id` - Foreign key to media\_resources
- `tag_id` - Foreign key to media\_tags

License
-------

[](#license)

This package is open-sourced software licensed under the [MIT license](LICENSE).

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

A **configurable media management package** for Laravel applications. Easily handle media uploads, storage, and metadata (images, videos, audio, and documents) in your Laravel backend projects using clean, reusable Actions and the Strategy Pattern.

> 💡 Perfect for projects where you want consistent, reusable media logic across multiple Laravel apps.

Features
--------

[](#features-1)

- 🎯 **Action-Based Architecture** - Clean, reusable Actions for all media operations
- 🏗️ **Strategy Pattern** - Extensible design for different media types
- 🖼️ **Automatic Thumbnails** - Generate thumbnails for images
- 📁 **Multiple Storage** - Support for local and external media
- 🔍 **Search &amp; Filter** - Built-in search and pagination
- 🏷️ **Tagging System** - Organize media with tags (auto-created, case-insensitive)
- 🛡️ **File Validation** - Configurable validation rules per media type
- 🚀 **Ready-to-use API** - Complete REST API endpoints
- 📝 **Comprehensive Logging** - Detailed error logging and debugging

---

Installation
------------

[](#installation-1)

Require the package via Composer:

```
composer require carone/laravel-media
```

Laravel will auto-discover the service provider.

Configuration
-------------

[](#configuration-3)

Publish the configuration file (optional):

```
php artisan vendor:publish --provider="Carone\Media\CaroneMediaServiceProvider" --tag=config
```

This creates a config/media.php file in your app.

Database Migration
------------------

[](#database-migration)

Run the included migration to create the media\_resources table

```
php artisan migrate
```

Table structure: (*Required fields are marked with \**)

ColumnTypeDescriptionid\*bigintPrimary keytype\*enum(image, video, audio, document)Type of mediasource\*enum(local, external)File sourcefile\_name\*stringOriginal file name (with extension)pathstringLocal storage pathurlstringExternal URL (if any)name\*stringReadable namedescriptiontextDescriptiondatedateDatemetajsonExtra metadatatimestamps\*—Created/updated timeQuick Start
-----------

[](#quick-start)

### Upload Media

[](#upload-media)

```
use Carone\Media\Actions\StoreMediaAction;

// Upload a local image with tags
$media = StoreMediaAction::run([
    'type' => 'image',
    'file' => $request->file('image'),
    'name' => 'My Beautiful Image',
    'description' => 'A description of the image',
    'tags' => ['Nature', 'Landscape', 'Photography'],
]);

// Upload external media with tags
$media = StoreMediaAction::run([
    'type' => 'video',
    'source' => 'external',
    'url' => 'https://www.youtube.com/watch?v=example',
    'name' => 'External Video',
    'tags' => ['Tutorial', 'Video'],
]);
```

### Get Media

[](#get-media)

```
use Carone\Media\Actions\GetMediaAction;

// Get media by type with pagination
$images = GetMediaAction::byType('image', $limit = 20, $offset = 0);

// Get single media item (includes tags)
$media = GetMediaAction::byId(1);
$tags = $media->tags; // Collection of Tag models

// Search media
$results = GetMediaAction::make()->search('vacation photos', 'image');
```

### Delete Media

[](#delete-media)

```
use Carone\Media\Actions\DeleteMediaAction;

// Delete single media (also removes tag associations)
$success = DeleteMediaAction::run($mediaId);

// Bulk delete
$result = DeleteMediaAction::make()->deleteMultiple([1, 2, 3]);
```

### Serve Files

[](#serve-files)

The package automatically provides routes for serving files:

```

        @foreach($media->tags as $tag)
            {{ $tag->name }}
        @endforeach

```

API Endpoints
-------------

[](#api-endpoints)

The package provides ready-to-use REST API endpoints:

```
GET    /api/media/types              # Get available media types
GET    /api/media/type/{type}        # Get media by type (paginated, includes tags)
GET    /api/media/search             # Search media (includes tags)
POST   /api/media/upload             # Upload media (accepts tags array)
GET    /api/media/{id}               # Get media by ID (includes tags)
DELETE /api/media/{id}               # Delete media
DELETE /api/media/bulk               # Bulk delete media

GET    /media/{type}/{filename}      # Serve media files
GET    /media/{type}/thumbnails/{filename} # Serve thumbnails

```

Migration from Existing Controllers
-----------------------------------

[](#migration-from-existing-controllers)

Replace your existing controller logic with Actions:

```
// Before (your existing controller)
public function uploadMedia(MediaUploadRequest $request)
{
    // ... complex upload logic ...
}

// After (using this package)
public function uploadMedia(Request $request)
{
    $media = StoreMediaAction::run([
        'type' => $request->input('type'),
        'file' => $request->file('file'),
        'name' => $request->input('name'),
        'tags' => $request->input('tags', []), // Optional tags
    ]);

    return response()->json([
        'success' => true,
        'media' => $media,
        'tags' => $media->tags->pluck('name'),
    ]);
}
```

Advanced Features
-----------------

[](#advanced-features)

### Custom Validation

[](#custom-validation)

Configure validation rules per media type:

```
// config/media.php
'validation' => [
    'image' => ['mimes:jpg,jpeg,png,gif', 'max:5120'], // 5MB max
    'video' => ['mimes:mp4,mov', 'max:51200'], // 50MB max
    'audio' => ['mimes:mp3,wav', 'max:10240'], // 10MB max
    'document' => ['mimes:pdf,doc,docx', 'max:10240'],
],
```

### Storage Configuration

[](#storage-configuration)

```
'disk' => env('DEFAULT_MEDIA_STORAGE_DISK', 'public'), // Main media files disk (not customizable per upload)
'storage_path' => 'media/{path}',
'enabled_types' => ['image', 'video', 'audio', 'document'],

// Thumbnail configuration
'thumbnails' => [
    'enabled' => true,
    'disk' => null, // If null, uses same disk as media. Can be customized per upload.
    'storage_path' => 'media/thumbnails/{path}',
],

// Tags configuration
'tags' => [
    'enabled' => true, // Enable/disable tagging system
],
```

**Important:** The main media disk is configured globally and cannot be overridden per upload. This ensures consistent, path-based media URLs. Thumbnails can still use custom disks.

### Route Protection

[](#route-protection)

The package provides separate public and protected routes:

**Public Routes** (no authentication required):

- `GET /api/media/types` - Get enabled media types
- `GET /api/media/type/{type}` - Browse media by type (includes tags)
- `GET /api/media/search` - Search media (includes tags)
- `GET /api/media/{id}` - Get media details (includes tags)
- `GET /media/{path}` - Serve media files
- `GET /media/thumbnails/{id}` - Serve thumbnails

**Protected Routes** (authentication required by default):

- `POST /api/media/upload` - Upload media (accepts tags)
- `DELETE /api/media/{id}` - Delete media (removes tag associations)
- `DELETE /api/media/bulk` - Bulk delete media

Configure protection in `config/media.php`:

```
'management_middleware' => ['auth'], // Default: require authentication

// Examples:
'management_middleware' => ['auth:sanctum'], // Use Sanctum
'management_middleware' => ['auth', 'admin'], // Require admin role
'management_middleware' => [], // No protection (not recommended for production)
```

### Error Handling

[](#error-handling-1)

All Actions throw appropriate exceptions:

```
try {
    $media = StoreMediaAction::run($data);
} catch (\InvalidArgumentException $e) {
    // Handle validation errors
} catch (\Exception $e) {
    // Handle general errors
}
```

Image Processing Driver Setup
-----------------------------

[](#image-processing-driver-setup)

The package supports two image processing drivers: **Imagick** and **GD**. Choose based on your application's needs.

### Driver Comparison

[](#driver-comparison)

FeatureImagickGD**Installation**Requires php-imagick extensionUsually built-in with PHP**Memory Usage**Streams data (~20-30 MB for 4000×4000)Loads full image (~180-200 MB for 4000×4000)**Large Images**Handles efficientlyRequires high memory\_limit**Performance**Generally fasterAdequate for small images**Availability**Needs separate installationBuilt into most PHP installs### Understanding Memory Behavior

[](#understanding-memory-behavior)

**Imagick** processes images by streaming data in chunks:

```
4000 × 4000 image = ~25-30 MB memory usage

```

**GD** loads the entire decompressed image into memory:

```
4000 × 4000 × 4 bytes (RGBA) = 64 MB base
+ Source buffer + processing buffers
= 180-200 MB total memory usage

```

### Which Driver to Choose?

[](#which-driver-to-choose)

**Choose Imagick if:**

- You handle large images (&gt;2000px dimensions)
- You have high-volume image uploads
- You need optimal memory efficiency
- You can install the php-imagick extension

**Choose GD if:**

- Your images are typically small (&lt;2000px)
- You have low upload volumes
- Imagick is not available in your environment
- You want to avoid additional dependencies

Both drivers are fully supported. The package defaults to Imagick but will automatically fall back to GD if Imagick is not installed.

### Installation

[](#installation-2)

#### Ubuntu/Debian

[](#ubuntudebian)

```
sudo apt-get update
sudo apt-get install php-imagick
sudo systemctl restart php-fpm  # or apache2/nginx
```

#### Windows

[](#windows)

1. Download the appropriate DLL from [PECL](https://pecl.php.net/package/imagick) or [windows.php.net](https://windows.php.net/downloads/pecl/releases/imagick/)
2. Place it in your PHP `ext` directory (e.g., `C:\php\ext\php_imagick.dll`)
3. Edit `php.ini` and add: ```
    extension=imagick
    ```
4. Restart your web server

#### macOS

[](#macos)

```
brew install imagemagick
pecl install imagick
```

Then add to your `php.ini`:

```
extension=imagick.so
```

### Verification

[](#verification)

After installation, verify your setup:

```
php artisan media:info
```

This will display:

- Active image driver and available extensions
- PHP memory limit and recommendations
- General media package configuration

Or check directly:

```
php -m | grep imagick
```

Configuration
-------------

[](#configuration-4)

The driver is configured in `config/media.php`:

```
'image_driver' => env('IMAGE_DRIVER', 'imagick'),
```

To use GD:

```
IMAGE_DRIVER=gd
```

### Oversized Image Handling

[](#oversized-image-handling)

The package can automatically scale down very large images to prevent memory issues and reduce storage:

```
// config/media.php
'processing' => [
    'image' => [
        'scale_oversized_images' => true,     // Enable/disable automatic scaling
        'max_dimension_before_encode' => 3000, // Threshold for scaling
        'scaled_max_dimension' => 2560,        // Target size (2.5K, still HD)
    ],
],
```

When enabled:

- 4000×4000 image → scaled to 2560×2560
- 2000×1500 image → kept at original size
- Works with both Imagick and GD drivers

Automatic Fallback
------------------

[](#automatic-fallback)

If Imagick is configured but not installed, the package will:

1. Log a warning
2. Automatically fall back to GD

Memory Recommendations
----------------------

[](#memory-recommendations)

### Recommended Settings

[](#recommended-settings)

For applications handling large images, configure adequate memory:

```
# php.ini
memory_limit = 256M  # Minimum recommended for large images (4000×4000)
```

### Memory Requirements by Image Size

[](#memory-requirements-by-image-size)

Image SizeMinimum memory\_limitRecommendedUp to 2000×2000128M256MUp to 4000×4000256M512MLarger than 4000×4000512M+1G**Note:** Imagick uses less memory than GD for the same images. With `scale_oversized_images` enabled, memory requirements are further reduced.

### Check Your Settings

[](#check-your-settings)

Run the info command to see your current configuration:

```
php artisan media:info
```

This will warn you if your memory limit is below the recommended 256M.

Troubleshooting
---------------

[](#troubleshooting)

### Error: "Imagick class not found"

[](#error-imagick-class-not-found)

- Extension is not installed or not enabled in php.ini
- Run: `php -m | grep imagick` to check

### Error: "Call to undefined function imagick\_..."

[](#error-call-to-undefined-function-imagick_)

- Wrong version of PHP or Imagick
- Reinstall: `pecl uninstall imagick && pecl install imagick`

### Still getting memory errors with Imagick

[](#still-getting-memory-errors-with-imagick)

- Check PHP memory limit: `php -i | grep memory_limit`
- Increase if needed: `memory_limit = 256M` (minimum)
- Verify Imagick is actually being used: `php artisan media:info`
- Enable `scale_oversized_images` in config

### Images look worse quality

[](#images-look-worse-quality)

- Check quality settings in `config/media.php`: ```
    'quality' => 85,  // 0-100, higher = better quality
    ```
- Verify `scale_oversized_images` settings if images are being scaled unexpectedly

### Want to disable automatic scaling

[](#want-to-disable-automatic-scaling)

- Set `scale_oversized_images` to `false` in config
- Ensure adequate memory\_limit for your image sizes

Performance Comparison
----------------------

[](#performance-comparison)

Testing with a 4000×4000 JPEG (5 MB on disk):

OperationGDImagickLoad image~180 MB RAM~25 MB RAMResize to 2560×2560~220 MB RAM~30 MB RAMGenerate thumbnail~250 MB RAM~35 MB RAMTotal time3.2s1.8s*Results may vary based on server configuration and image complexity.*

Summary
-------

[](#summary)

Both drivers work well for their intended use cases:

- **Imagick**: Best for applications with large images or high upload volumes
- **GD**: Suitable for applications with small images or where Imagick is unavailable

The package is configured to use Imagick by default but will work seamlessly with either driver.

Documentation
-------------

[](#documentation)

For detailed usage examples and advanced features, see [USAGE.md](USAGE.md).

Architecture
------------

[](#architecture)

This package uses:

- **Actions** (via `lorisleiva/laravel-actions`) for clean, reusable operations
- **Strategy Pattern** for handling different media types
- **Dependency Injection** for extensibility
- **Laravel's Storage** system for file management

License
-------

[](#license-1)

This package is open-sourced software licensed under the MIT license.

💬 **About**

carone/laravel-media is built for developers who need consistent, configurable media handling across multiple Laravel projects — without duplicating models, migrations, or upload logic.

**Designed for backend efficiency.**
**Presentation is up to you.** 🎨

###  Health Score

37

—

LowBetter than 83% of packages

Maintenance78

Regular maintenance activity

Popularity6

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~9 days

Total

3

Last Release

114d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/c0f820aee6fd5e896865c14d04a7776ece292213e788023bc07a1ea63e6206c1?d=identicon)[carone](/maintainers/carone)

---

Top Contributors

[![EmileCar](https://avatars.githubusercontent.com/u/114223326?v=4)](https://github.com/EmileCar "EmileCar (29 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/carone-laravel-media/health.svg)

```
[![Health](https://phpackages.com/badges/carone-laravel-media/health.svg)](https://phpackages.com/packages/carone-laravel-media)
```

###  Alternatives

[intervention/image-laravel

Laravel Integration of Intervention Image

1496.5M102](/packages/intervention-image-laravel)[bkwld/croppa

Image thumbnail creation through specially formatted URLs for Laravel

510496.0k23](/packages/bkwld-croppa)[fumeapp/modeltyper

Generate TypeScript interfaces from Laravel Models

196277.9k](/packages/fumeapp-modeltyper)[ace-of-aces/laravel-image-transform-url

Easy, URL-based image transformations inspired by Cloudflare Images.

1756.4k](/packages/ace-of-aces-laravel-image-transform-url)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

255.2k](/packages/aedart-athenaeum)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
