Skip to main content

Overview

The Photo model represents individual photos in LaraCMS. It integrates with Spatie Media Library for image storage and manipulation, and can belong to multiple albums. Namespace: App\Models\Photo Extends: Illuminate\Database\Eloquent\Model Implements: Spatie\MediaLibrary\HasMedia Traits:
  • InteractsWithMedia - Spatie Media Library integration

Properties

Table Name

protected $table = 'photos';

Fillable Attributes

title
string
required
The title or name of the photo
description
text
Detailed description or caption for the photo

Relationships

albums()

Type: belongsToMany Related Model: App\Models\Album Pivot Table: album_photo Foreign Key: photo_id Related Key: album_id Description: Returns all albums that contain this photo. A photo can belong to multiple albums.
public function albums()
{
    return $this->belongsToMany(Album::class, 'album_photo', 'photo_id', 'album_id');
}
Example:
$photo = Photo::find(1);
$albums = $photo->albums;

foreach ($albums as $album) {
    echo $album->album_name;
}

Methods

registerMediaCollections()

Returns: void Description: Registers the ‘images’ media collection for storing photo files. Unlike single-file collections, this allows multiple images to be associated with a photo if needed.
public function registerMediaCollections(): void
{
    $this->addMediaCollection('images');
}
Example:
$photo = Photo::find(1);

// Add image to the collection
$photo->addMedia($request->file('image'))
    ->toMediaCollection('images');

registerMediaConversions()

Parameters:
  • $media - Spatie\MediaLibrary\MediaCollections\Models\Media|null
Returns: void Description: Defines image conversions for uploaded photos. Creates a ‘preview’ conversion that fits the image to 300x300 pixels for thumbnails and previews.
public function registerMediaConversions(?Media $media = null): void
{
    $this
        ->addMediaConversion('preview')
        ->fit(Fit::Contain, 300, 300)
        ->nonQueued();
}

Usage Examples

Creating a Photo

use App\Models\Photo;

$photo = Photo::create([
    'title' => 'Sunset at the Beach',
    'description' => 'Beautiful sunset captured at Santa Monica Beach',
]);

Adding Image Files

$photo = Photo::find(1);

// Add a single image
$photo->addMedia($request->file('image'))
    ->toMediaCollection('images');

// Add image from path
$photo->addMedia('/path/to/image.jpg')
    ->toMediaCollection('images');

// Add image from URL
$photo->addMediaFromUrl('https://example.com/image.jpg')
    ->toMediaCollection('images');

Retrieving Images

$photo = Photo::find(1);

// Get first image URL
$imageUrl = $photo->getFirstMediaUrl('images');

// Get preview (thumbnail) URL
$thumbnailUrl = $photo->getFirstMediaUrl('images', 'preview');

// Get all images in collection
$images = $photo->getMedia('images');

foreach ($images as $image) {
    echo $image->getUrl();
    echo $image->getUrl('preview'); // Thumbnail version
}

// Check if photo has images
if ($photo->hasMedia('images')) {
    // Photo has images
}

Working with Albums

$photo = Photo::find(1);

// Attach photo to album
$photo->albums()->attach($albumId);

// Attach to multiple albums
$photo->albums()->attach([1, 2, 3]);

// Sync albums (replace all existing)
$photo->albums()->sync([1, 2]);

// Detach from album
$photo->albums()->detach($albumId);

// Detach from all albums
$photo->albums()->detach();

// Get album count
$albumCount = $photo->albums()->count();

Querying Photos

// Get all photos
$photos = Photo::all();

// Find by title
$photo = Photo::where('title', 'Sunset at the Beach')->first();

// Search photos
$photos = Photo::where('title', 'like', '%sunset%')
    ->orWhere('description', 'like', '%sunset%')
    ->get();

// Get recent photos
$recentPhotos = Photo::orderBy('created_at', 'desc')
    ->limit(10)
    ->get();

// Get photos in specific album
$album = Album::find(1);
$photos = $album->photos;

Eager Loading

// Load photos with albums
$photos = Photo::with('albums')->get();

// Load photos with media
$photos = Photo::with('media')->get();

// Load both
$photos = Photo::with(['albums', 'media'])->get();

// With album count
$photos = Photo::withCount('albums')->get();

foreach ($photos as $photo) {
    echo "{$photo->title} is in {$photo->albums_count} albums";
}

Updating Photos

$photo = Photo::find(1);

$photo->update([
    'title' => 'Updated Photo Title',
    'description' => 'Updated description',
]);

// Update and change image
$photo->update(['title' => 'New Title']);

// Clear old images and add new one
$photo->clearMediaCollection('images');
$photo->addMedia($request->file('new_image'))
    ->toMediaCollection('images');

Deleting Photos

$photo = Photo::find(1);

// Delete photo (automatically removes media files)
$photo->delete();

// Detach from albums before deleting
$photo->albums()->detach();
$photo->delete();

// Delete specific media
$media = $photo->getFirstMedia('images');
$media->delete();

Advanced Media Operations

$photo = Photo::find(1);

// Add media with custom properties
$photo->addMedia($request->file('image'))
    ->withCustomProperties(['photographer' => 'John Doe'])
    ->toMediaCollection('images');

// Get media with properties
$media = $photo->getFirstMedia('images');
$photographer = $media->getCustomProperty('photographer');

// Set media name
$photo->addMedia($request->file('image'))
    ->usingName('Beach Sunset')
    ->toMediaCollection('images');

// Set file name
$photo->addMedia($request->file('image'))
    ->usingFileName('custom-name.jpg')
    ->toMediaCollection('images');

Database Schema

The photos table includes:
  • id - Primary key
  • title - Photo title
  • description - Photo description/caption
  • created_at - Timestamp
  • updated_at - Timestamp

Pivot Tables

album_photo:
  • album_id - Foreign key to album table
  • photo_id - Foreign key to photos table
  • Album - Albums containing this photo

Media Storage

Photos use Spatie Media Library for file storage:
  • Original images are stored in the configured media disk
  • Preview conversions (300x300) are automatically generated
  • Media files are automatically deleted when the photo is deleted
  • Supports multiple file formats (JPEG, PNG, GIF, WebP, etc.)

Build docs developers (and LLMs) love