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();
}
}