/ CRUD Operations

CRUD Operations Examples

Complete examples of Create, Read, Update, and Delete operations using Miko ORM.


Model Definition

use Miko\Database\ORM\Model;
use Miko\Database\ORM\Traits\{HasTimestamps, SoftDeletes};

class User extends Model
{
    use HasTimestamps, SoftDeletes;
    
    protected static string $table = 'users';
    protected string $primaryKey = 'Id';
    
    protected array $fillable = [
        'Name', 'Email', 'Password', 'Role', 'IsActive'
    ];
    
    protected array $hidden = ['Password'];
    
    protected array $casts = [
        'IsActive' => 'boolean',
        'Age' => 'integer'
    ];
}

Create Operations

Method 1: create()

// Create and save in one step
$user = User::create([
    'Name' => 'John Doe',
    'Email' => 'john@example.com',
    'Password' => password_hash('secret', PASSWORD_DEFAULT),
    'Role' => 'user',
    'IsActive' => true
]);

echo "Created user ID: " . $user->Id;

Method 2: new + save()

// Create instance, set properties, then save
$user = new User();
$user->Name = 'Jane Doe';
$user->Email = 'jane@example.com';
$user->Password = password_hash('secret', PASSWORD_DEFAULT);
$user->Role = 'admin';
$user->save();

echo "Created user ID: " . $user->Id;

Method 3: fill() + save()

// Fill from array and save
$user = new User();
$user->fill([
    'Name' => 'Bob Smith',
    'Email' => 'bob@example.com',
    'Role' => 'user'
]);
$user->Password = password_hash('secret', PASSWORD_DEFAULT);
$user->save();

firstOrCreate()

// Find existing or create new
$user = User::firstOrCreate(
    ['Email' => 'john@example.com'],  // Search criteria
    ['Name' => 'John Doe', 'Role' => 'user']  // Create with these if not found
);

firstOrNew()

// Find existing or create instance (not saved)
$user = User::firstOrNew(
    ['Email' => 'john@example.com'],
    ['Name' => 'John Doe']
);

if (!$user->exists) {
    $user->Password = password_hash('secret', PASSWORD_DEFAULT);
    $user->save();
}

Read Operations

Find by ID

// Find single record
$user = User::find(1);

if ($user) {
    echo $user->Name;
}

// Find or throw exception
$user = User::findOrFail(1);  // Throws ModelNotFoundException

// Find multiple
$users = User::findMany([1, 2, 3, 4, 5]);

Get All

// Get all records
$users = User::all();

foreach ($users as $user) {
    echo $user->Name . "\n";
}

First Record

// Get first record
$user = User::first();

// First with condition
$admin = User::where('Role', 'admin')->first();

// First or fail
$user = User::where('Email', 'john@example.com')->firstOrFail();

Where Conditions

// Simple where
$activeUsers = User::where('IsActive', true)->get();

// With operator
$adults = User::where('Age', '>=', 18)->get();

// Multiple conditions
$admins = User::where('Role', 'admin')
    ->where('IsActive', true)
    ->get();

// OR condition
$staff = User::where('Role', 'admin')
    ->orWhere('Role', 'moderator')
    ->get();

// Grouped where — WHERE IsActive = ? AND (Role = ? OR Role = ?)
$staff = User::where('IsActive', true)
    ->where(function ($q) {
        $q->where('Role', 'admin')
          ->orWhere('Role', 'moderator');
    })
    ->get();

// WHERE IN
$users = User::whereIn('Id', [1, 2, 3])->get();

// WHERE BETWEEN
$users = User::whereBetween('Age', 18, 65)->get();

// WHERE NULL
$unverified = User::whereNull('EmailVerifiedAt')->get();

// WHERE LIKE
$johns = User::whereLike('Name', 'john')->get();

Ordering

// Order by
$users = User::orderBy('Name')->get();
$users = User::orderBy('CreatedDate', 'desc')->get();

// Latest / Oldest
$newest = User::latest()->first();
$oldest = User::oldest()->first();

Limiting

// Take / Limit
$users = User::take(10)->get();

// Skip / Offset
$users = User::skip(20)->take(10)->get();

Pagination

$result = User::where('IsActive', true)
    ->orderBy('Name')
    ->paginate(20, 1); // per page, page number

echo 'Page: ' . $result['current_page'];
echo 'Total: ' . $result['total'];

foreach ($result['data'] as $user) {
    echo $user->Name;
}

Aggregates

$count = User::count();
$activeCount = User::where('IsActive', true)->count();

$avgAge = User::avg('Age');
$totalSales = Order::sum('TotalAmount');

$minPrice = Product::min('Price');
$maxPrice = Product::max('Price');

$exists = User::where('Email', 'john@example.com')->exists();

Update Operations

Method 1: Find and Update

$user = User::find(1);
$user->Name = 'John Updated';
$user->Email = 'john.updated@example.com';
$user->save();

Method 2: fill() and save()

$user = User::find(1);
$user->fill([
    'Name' => 'John Updated',
    'Role' => 'admin'
]);
$user->save();

Method 3: update() (Mass Update)

// Update all matching records
User::where('Role', 'guest')
    ->update(['Role' => 'user']);

// Update with multiple conditions
User::where('IsActive', false)
    ->where('LastLoginAt', '<', '2023-01-01')
    ->update(['Status' => 'inactive']);

updateOrCreate()

// Update if exists, create if not
$user = User::updateOrCreate(
    ['Email' => 'john@example.com'],  // Find by
    [
        'Name' => 'John Doe',
        'Role' => 'admin',
        'IsActive' => true
    ]  // Update/Create with
);

Increment / Decrement

// Increment
$user->increment('LoginCount');
$user->increment('Points', 10);

// Decrement
$product->decrement('Stock');
$product->decrement('Stock', 5);

Touch (Update Timestamps)

// Update UpdatedDate to current time
$user->touch();

Delete Operations

Soft Delete

// Soft delete (sets DeletedAt)
$user = User::find(1);
$user->delete();

// Check if soft deleted
if ($user->trashed()) {
    echo "User is deleted";
}

Restore

// Restore soft deleted record
$user = User::withTrashed()->find(1);
$user->restore();

Force Delete

// Permanent delete
$user = User::find(1);
$user->forceDelete();

Delete by ID

// Delete single
User::destroy(1);

// Delete multiple
User::destroy([1, 2, 3, 4, 5]);

Delete with Condition

// Delete matching records
User::where('IsActive', false)
    ->where('CreatedDate', '<', '2020-01-01')
    ->delete();

Query Soft Deleted

// Include soft deleted
$allUsers = User::withTrashed()->get();

// Only soft deleted
$deletedUsers = User::onlyTrashed()->get();

// Exclude soft deleted (default)
$activeUsers = User::all();

Complete API Example

class UserController
{
    // GET /users
    public function index(): void
    {
        $page = (int)($_GET['page'] ?? 1);
        $perPage = (int)($_GET['per_page'] ?? 20);
        
        $result = User::where('IsActive', true)
            ->orderBy('Name')
            ->paginate($perPage, $page);
        
        JsonResponse::paginated(
            array_map(fn($u) => $u->only('Id', 'Name', 'Email'), $result['data']),
            [
                'current_page' => $result['current_page'],
                'last_page' => $result['last_page'],
                'total' => $result['total'],
            ]
        );
    }
    
    // GET /users/{id}
    public function show(int $id): void
    {
        $user = User::find($id);
        
        if (!$user) {
            JsonResponse::notFound('User not found');
            return;
        }
        
        JsonResponse::success($user->only('Id', 'Name', 'Email', 'Role'));
    }
    
    // POST /users
    public function store(): void
    {
        $data = json_decode(file_get_contents('php://input'), true);
        
        $user = User::create([
            'Name' => $data['name'],
            'Email' => $data['email'],
            'Password' => password_hash($data['password'], PASSWORD_DEFAULT),
            'Role' => 'user',
            'IsActive' => true
        ]);
        
        JsonResponse::created($user->only('Id', 'Name', 'Email'));
    }
    
    // PUT /users/{id}
    public function update(int $id): void
    {
        $user = User::find($id);
        
        if (!$user) {
            JsonResponse::notFound('User not found');
            return;
        }
        
        $data = json_decode(file_get_contents('php://input'), true);
        
        $user->fill([
            'Name' => $data['name'] ?? $user->Name,
            'Email' => $data['email'] ?? $user->Email
        ]);
        $user->save();
        
        JsonResponse::success($user->only('Id', 'Name', 'Email'));
    }
    
    // DELETE /users/{id}
    public function destroy(int $id): void
    {
        $user = User::find($id);
        
        if (!$user) {
            JsonResponse::notFound('User not found');
            return;
        }
        
        $user->delete();
        JsonResponse::noContent();
    }
}