Skip to content

Examples

Jean-Marc Strauven edited this page Aug 1, 2025 · 1 revision

Examples Collection

This page contains practical examples demonstrating various Laravel Snapshot features and use cases.

Quick Start Examples

1. Basic Usage

Simple snapshot creation and comparison:

use App\Models\User;
use Grazulex\LaravelSnapshot\Snapshot;

// Create a test user
$user = User::factory()->create([
    'name' => 'John Doe',
    'email' => 'john@example.com',
]);

// Create initial snapshot
Snapshot::save($user, 'user-initial');

// Modify the user
$user->update([
    'name' => 'John Smith',
    'email' => 'john.smith@example.com',
]);

// Create second snapshot
Snapshot::save($user, 'user-updated');

// Compare snapshots
$diff = Snapshot::diff('user-initial', 'user-updated');

// Display changes
foreach ($diff['modified'] as $field => $changes) {
    echo "{$field}: '{$changes['from']}' β†’ '{$changes['to']}'";
}

2. Model with HasSnapshots Trait

Using the convenient trait methods:

use Grazulex\LaravelSnapshot\Traits\HasSnapshots;
use Illuminate\Database\Eloquent\Model;

class Order extends Model
{
    use HasSnapshots;
    
    protected $fillable = ['customer_name', 'total', 'status'];
}

// Create order with automatic snapshot
$order = Order::create([
    'customer_name' => 'Jane Doe',
    'total' => 99.99,
    'status' => 'pending'
]);

// Create labeled snapshot
$order->snapshot('order-created');

// Get all snapshots for this order
$snapshots = $order->snapshots;

// Get timeline
$timeline = $order->getSnapshotTimeline();

// Generate HTML report
$report = $order->getHistoryReport('html');

3. Console Commands

Command-line examples:

# Create a snapshot
php artisan snapshot:save "App\Models\User" --id=1 --label=before-update

# List all snapshots
php artisan snapshot:list

# Compare two snapshots
php artisan snapshot:diff before-update after-update

# Generate a report
php artisan snapshot:report --model="App\Models\User" --id=1

Real-World Use Cases

4. E-commerce Order Processing

Track order changes through processing pipeline:

use App\Models\Order;
use Grazulex\LaravelSnapshot\Snapshot;

class OrderProcessor
{
    public function processOrder(Order $order)
    {
        // Snapshot before processing
        Snapshot::save($order, "order-{$order->id}-processing-start");
        
        // Apply discount
        $order->update(['total' => $order->total * 0.9]);
        Snapshot::save($order, "order-{$order->id}-discount-applied");
        
        // Calculate tax
        $order->update(['tax' => $order->total * 0.1]);
        Snapshot::save($order, "order-{$order->id}-tax-calculated");
        
        // Update status
        $order->update(['status' => 'processed']);
        Snapshot::save($order, "order-{$order->id}-processing-complete");
        
        // Generate processing report
        return $this->generateProcessingReport($order);
    }
    
    private function generateProcessingReport(Order $order)
    {
        $snapshots = [
            "order-{$order->id}-processing-start",
            "order-{$order->id}-discount-applied", 
            "order-{$order->id}-tax-calculated",
            "order-{$order->id}-processing-complete"
        ];
        
        $report = [];
        for ($i = 0; $i < count($snapshots) - 1; $i++) {
            $diff = Snapshot::diff($snapshots[$i], $snapshots[$i + 1]);
            $report[] = [
                'step' => $i + 1,
                'from' => $snapshots[$i],
                'to' => $snapshots[$i + 1],
                'changes' => $diff
            ];
        }
        
        return $report;
    }
}

5. User Profile Auditing

Audit trail for user profile changes:

use App\Models\User;
use Grazulex\LaravelSnapshot\Traits\HasSnapshots;

class User extends Model
{
    use HasSnapshots;
    
    protected $fillable = ['name', 'email', 'profile'];
    
    // Automatically create snapshots on important changes
    protected $snapshotEvents = ['updated'];
    
    public function updateProfile(array $profileData)
    {
        // Snapshot before update
        $this->snapshot('profile-before-update-' . time());
        
        // Update profile
        $this->update(['profile' => array_merge($this->profile ?? [], $profileData)]);
        
        // Snapshot after update
        $this->snapshot('profile-after-update-' . time());
        
        return $this;
    }
    
    public function getAuditTrail()
    {
        return $this->snapshots()
            ->where('label', 'like', 'profile-%')
            ->orderBy('created_at')
            ->get()
            ->map(function ($snapshot) {
                return [
                    'timestamp' => $snapshot->created_at,
                    'label' => $snapshot->label,
                    'changes' => $this->getSnapshotChanges($snapshot)
                ];
            });
    }
}

6. Automated Testing

Using snapshots in feature tests:

use Tests\TestCase;
use App\Models\User;
use Grazulex\LaravelSnapshot\Snapshot;
use Grazulex\LaravelSnapshot\Storage\ArrayStorage;

class UserUpdateTest extends TestCase
{
    protected function setUp(): void
    {
        parent::setUp();
        
        // Use memory storage for tests
        Snapshot::setStorage(new ArrayStorage());
    }
    
    public function test_user_update_changes_are_tracked()
    {
        $user = User::factory()->create(['name' => 'Original Name']);
        
        // Create initial snapshot
        Snapshot::save($user, 'test-initial');
        
        // Update user
        $user->update(['name' => 'Updated Name']);
        Snapshot::save($user, 'test-updated');
        
        // Assert changes
        $diff = Snapshot::diff('test-initial', 'test-updated');
        
        $this->assertArrayHasKey('modified', $diff);
        $this->assertArrayHasKey('name', $diff['modified']);
        $this->assertEquals('Original Name', $diff['modified']['name']['from']);
        $this->assertEquals('Updated Name', $diff['modified']['name']['to']);
    }
    
    public function test_user_deletion_is_tracked()
    {
        $user = User::factory()->create();
        
        // Snapshot before deletion
        Snapshot::save($user, 'test-before-delete');
        
        $userId = $user->id;
        $user->delete();
        
        // Verify snapshot exists after deletion
        $snapshot = Snapshot::load('test-before-delete');
        $this->assertEquals($userId, $snapshot['attributes']['id']);
    }
}

Advanced Features

7. Custom Storage Backend

Implement custom storage driver:

use Grazulex\LaravelSnapshot\Contracts\SnapshotStorage;

class RedisSnapshotStorage implements SnapshotStorage
{
    protected $redis;
    protected $prefix;
    
    public function __construct($redis, $prefix = 'snapshots:')
    {
        $this->redis = $redis;
        $this->prefix = $prefix;
    }
    
    public function save(string $label, array $data): bool
    {
        return $this->redis->set(
            $this->prefix . $label,
            json_encode($data)
        );
    }
    
    public function load(string $label): ?array
    {
        $data = $this->redis->get($this->prefix . $label);
        return $data ? json_decode($data, true) : null;
    }
    
    public function delete(string $label): bool
    {
        return $this->redis->del($this->prefix . $label) > 0;
    }
    
    public function list(): array
    {
        $keys = $this->redis->keys($this->prefix . '*');
        $snapshots = [];
        
        foreach ($keys as $key) {
            $label = str_replace($this->prefix, '', $key);
            $data = $this->load($label);
            if ($data) {
                $snapshots[$label] = $data;
            }
        }
        
        return $snapshots;
    }
    
    public function exists(string $label): bool
    {
        return $this->redis->exists($this->prefix . $label) > 0;
    }
}

// Usage
$redisStorage = new RedisSnapshotStorage(app('redis')->connection());
Snapshot::setStorage($redisStorage);

8. Scheduled Snapshots

Periodic automatic snapshots:

use Illuminate\Console\Command;
use App\Models\User;
use Grazulex\LaravelSnapshot\Snapshot;

class CreateScheduledSnapshots extends Command
{
    protected $signature = 'snapshots:create-scheduled';
    protected $description = 'Create scheduled snapshots for important models';
    
    public function handle()
    {
        $timestamp = now()->format('Y-m-d-H-i-s');
        
        // Snapshot all active users
        User::where('active', true)->chunk(100, function ($users) use ($timestamp) {
            foreach ($users as $user) {
                Snapshot::save($user, "scheduled-user-{$user->id}-{$timestamp}");
            }
        });
        
        $this->info('Scheduled snapshots created successfully');
    }
}

// In app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
    $schedule->command('snapshots:create-scheduled')
             ->dailyAt('02:00')
             ->when(function () {
                 return config('snapshot.scheduled_enabled', false);
             });
}

Running Examples

All examples can be run in several ways:

Method 1: Tinker (Recommended)

php artisan tinker

Then copy and paste any example code.

Method 2: Artisan Command

Create a custom command to run examples:

php artisan make:command RunExample

Method 3: Test Environment

Run examples in a test case to ensure they work correctly.

Download Example Files

For convenience, you can download the complete example files:

Next Steps

After exploring these examples:

  1. Learn about configuration options
  2. Explore advanced usage patterns
  3. Set up automatic snapshots
  4. Generate reports and analytics
Clone this wiki locally