PHP code example of brighten / immutable-model

1. Go to this page and download the library: Download brighten/immutable-model library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

brighten / immutable-model example snippets


use Brighten\ImmutableModel\ImmutableModel;

class UserView extends ImmutableModel
{
    protected string $table = 'user_views';

    protected ?string $primaryKey = 'id';

    protected array $casts = [
        'settings' => 'array',
        'created_at' => 'datetime',
    ];
}

// Query just like Eloquent
$users = UserView::where('active', true)->get();
$user = UserView::find(1);
$user = UserView::with('posts')->first();

// In-memory changes are allowed (for computed fields, API responses, etc.)
$user->computed_field = 'some value';  // Works fine
$user->name = 'Modified';              // Works fine (in-memory only)

// But database persistence is blocked
$user->save();              // Throws ImmutableModelViolationException
$user->update([...]);       // Throws ImmutableModelViolationException
$user->delete();            // Throws ImmutableModelViolationException
UserView::create([...]);    // Throws ImmutableModelViolationException

class MyModel extends ImmutableModel
{
    // Required: The database table
    protected string $table = 'my_table';

    // Optional: Primary key (null = non-identifiable model)
    protected ?string $primaryKey = 'id';

    // Optional: Database connection (null = default)
    protected ?string $connection = null;

    // Optional: Attribute casting
    protected array $casts = [
        'settings' => 'array',
        'created_at' => 'datetime',
    ];

    // Optional: Relations to eager load by default
    protected array $with = ['author'];

    // Optional: Accessors to append to array/JSON output
    protected array $appends = ['full_name'];

    // Optional: Hidden attributes
    protected array $hidden = ['internal_id'];

    // Optional: Visible attributes (whitelist)
    protected array $visible = ['id', 'name', 'email'];
}

// Finding records
MyModel::find($id);
MyModel::findOrFail($id);
MyModel::first();
MyModel::all();

// Where clauses
MyModel::where('status', 'active')
    ->where('created_at', '>', now()->subWeek())
    ->orWhere('featured', true)
    ->whereIn('category_id', [1, 2, 3])
    ->whereNotNull('published_at')
    ->get();

// Ordering & limiting
MyModel::orderBy('created_at', 'desc')
    ->limit(10)
    ->offset(20)
    ->get();

// Aggregates
MyModel::count();
MyModel::sum('price');
MyModel::avg('rating');
MyModel::max('views');

class Post extends ImmutableModel
{
    protected string $table = 'posts';

    public function author()
    {
        return $this->belongsTo(User::class, 'user_id', 'id');
    }

    public function comments()
    {
        return $this->hasMany(Comment::class, 'post_id', 'id');
    }

    public function featuredImage()
    {
        return $this->hasOne(Image::class, 'post_id', 'id');
    }
}

// Eager loading
$posts = Post::with('author', 'comments')->get();

// Eager loading with constraints
$posts = Post::with(['comments' => fn($q) => $q->where('approved', true)])->get();

// Lazy loading (works, but watch for N+1)
$post = Post::find(1);
$author = $post->author;

// Relation queries
$comments = $post->comments()->where('approved', true)->get();

protected array $casts = [
    // Scalar types
    'count' => 'int',
    'price' => 'float',
    'active' => 'bool',
    'name' => 'string',

    // Date/time
    'published_at' => 'datetime',
    'birthday' => 'date',
    'updated_at' => 'immutable_datetime',
    'timestamp' => 'timestamp',

    // Complex types
    'settings' => 'array',
    'metadata' => 'json',
    'tags' => 'collection',

    // Custom casters
    'address' => AddressCast::class,
];

$users = User::all();

// All collection operations work normally
$active = $users->filter(fn($u) => $u->active);
$sorted = $users->sortBy('name');
$names = $users->pluck('name');
$mapped = $users->map(fn($u) => $u->toArray());
$users->push($newUser);     // Works - this is in-memory only
$users->transform(fn($u) => $u);  // Works

// In-memory model changes are allowed
$users->first()->name = 'New';       // Works (in-memory only)
$users->first()->computed = 'value'; // Works (add computed fields)

// But database persistence is blocked
$users->first()->save();   // Throws ImmutableModelViolationException
$users->first()->delete(); // Throws ImmutableModelViolationException

$paginated = MyModel::paginate(15);
$simple = MyModel::simplePaginate(15);
$cursor = MyModel::cursorPaginate(15);

// Chunk for batch processing
MyModel::chunk(1000, function ($models) {
    foreach ($models as $model) {
        // Process
    }
});

// Cursor for memory-efficient iteration
foreach (MyModel::cursor() as $model) {
    // Process one at a time
}

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;

class TenantScope implements Scope
{
    public function apply(Builder $builder, Model $model): void
    {
        $builder->where('tenant_id', auth()->user()->tenant_id);
    }
}

class TenantModel extends ImmutableModel
{
    protected static function booted(): void
    {
        static::addGlobalScope(new TenantScope);
    }
}

// Bypass scopes when needed
TenantModel::withoutGlobalScopes()->get();
TenantModel::withoutGlobalScope(TenantScope::class)->get();

// Single model
$user = User::fromRow(['id' => 1, 'name' => 'John']);

// Collection of models
$users = User::fromRows([
    ['id' => 1, 'name' => 'John'],
    ['id' => 2, 'name' => 'Jane'],
]);