Nhảy tới nội dung

Model (ORM)

Model là lớp đại diện cho một bảng trong database, cho phép tương tác với dữ liệu theo hướng đối tượng.

Định nghĩa Model

<?php

namespace App\Models;

use Vietiso\Core\Database\Model\Model;

class User extends Model
{
// Tên bảng (mặc định là snake_case của tên class + 's')
protected string $table = 'users';

// Primary key (mặc định là 'id')
protected ?string $primaryKey = 'id';

// Có dùng auto-increment không
protected bool $incrementing = true;

// Có dùng timestamps không (created_at, updated_at)
public bool $timestamps = true;

// Connection database (null = default)
protected ?string $connection = null;
}

Truy vấn cơ bản

use App\Models\User;

// Lấy tất cả
$users = User::get();

// Lấy theo ID
$user = User::find(1);

// Lấy hoặc throw exception
$user = User::findOrFail(1);

// Lấy record đầu tiên
$user = User::where('status', 'active')->first();

// Đếm
$count = User::where('role', 'admin')->count();

Tạo mới

// Tạo và lưu
$user = User::create([
'name' => 'John',
'email' => 'john@example.com',
]);

// firstOrCreate - tìm hoặc tạo mới
$user = User::firstOrCreate(
['email' => 'john@example.com'], // điều kiện tìm
['name' => 'John'] // dữ liệu tạo mới
);

// firstOrNew - tìm hoặc tạo instance (chưa save)
$user = User::firstOrNew(
['email' => 'john@example.com'],
['name' => 'John']
);

// updateOrCreate - cập nhật hoặc tạo mới
$user = User::updateOrCreate(
['email' => 'john@example.com'],
['name' => 'John Doe', 'role' => 'admin']
);

Cập nhật

// Cập nhật instance
$user = User::find(1);
$user->name = 'Jane';
$user->save();

// Update trực tiếp
User::where('id', 1)->update(['name' => 'Jane']);

// Cập nhật nhiều records
User::where('status', 'pending')
->update(['status' => 'active']);

Xóa

// Xóa instance
$user = User::find(1);
$user->delete();

// Xóa trực tiếp
User::where('id', 1)->delete();

// Xóa nhiều records
User::where('status', 'inactive')->delete();

Soft Deletes

<?php

namespace App\Models;

use Vietiso\Core\Database\Model\Model;
use Vietiso\Core\Database\Model\Traits\SoftDeletes;

class User extends Model
{
use SoftDeletes;
}
// Xóa mềm (set deleted_at)
$user->delete();

// Kiểm tra đã xóa mềm
if ($user->trashed()) {
// ...
}

// Bao gồm cả records đã xóa mềm
$users = User::withTrashed()->get();

// Chỉ lấy records đã xóa mềm
$users = User::onlyTrashed()->get();

// Khôi phục record đã xóa mềm
$user->restore();

// Xóa vĩnh viễn
$user->forceDelete();

Accessors & Mutators

Sử dụng attributes để định nghĩa accessors và mutators:

<?php

namespace App\Models;

use Vietiso\Core\Database\Model\Model;
use Vietiso\Core\Database\Attributes\Accessor;
use Vietiso\Core\Database\Attributes\Mutator;

class User extends Model
{
// Accessor - chuyển đổi khi lấy dữ liệu
#[Accessor('name')]
public function getNameAttribute(string $value): string
{
return ucfirst($value);
}

// Mutator - chuyển đổi khi gán dữ liệu
#[Mutator('password')]
public function setPasswordAttribute(string $value): string
{
return password_hash($value, PASSWORD_DEFAULT);
}

// Accessor cho computed attribute
#[Accessor('full_name')]
public function getFullNameAttribute(): string
{
return "{$this->first_name} {$this->last_name}";
}
}
$user = User::find(1);
echo $user->full_name; // John Doe

Attribute Casting

<?php

namespace App\Models;

use Vietiso\Core\Database\Model\Model;

class User extends Model
{
protected array $casts = [
'is_active' => 'boolean',
'settings' => 'array',
'birthday' => 'date',
'created_at' => 'datetime',
'price' => 'float',
'count' => 'integer',
];
}

Custom Casts

<?php

namespace App\Casts;

use Vietiso\Core\Database\Model\Casts\CastsAttributes;

class JsonCast implements CastsAttributes
{
public function get($model, string $key, $value, array $attributes): array
{
return json_decode($value, true) ?? [];
}

public function set($model, string $key, $value, array $attributes): string
{
return json_encode($value);
}
}
protected array $casts = [
'metadata' => JsonCast::class,
];

Relationships

One to One

<?php

namespace App\Models;

use Vietiso\Core\Database\Model\Model;
use Vietiso\Core\Database\Attributes\HasOne;
use Vietiso\Core\Database\Attributes\BelongsTo;

class User extends Model
{
#[HasOne(Profile::class, 'user_id')]
public function profile() {}
}

class Profile extends Model
{
#[BelongsTo(User::class, 'user_id')]
public function user() {}
}

One to Many

<?php

namespace App\Models;

use Vietiso\Core\Database\Model\Model;
use Vietiso\Core\Database\Attributes\HasMany;
use Vietiso\Core\Database\Attributes\BelongsTo;

class User extends Model
{
#[HasMany(Post::class, 'user_id')]
public function posts() {}
}

class Post extends Model
{
#[BelongsTo(User::class, 'user_id')]
public function user() {}
}

Sử dụng Relationships

// Eager loading
$users = User::with('posts')->get();

// Nested eager loading
$users = User::with('posts.comments')->get();

// Lazy loading
$user = User::find(1);
$posts = $user->posts;

// Query relationship
$user = User::find(1);
$publishedPosts = $user->posts()->where('status', 'published')->get();

Global Scopes

<?php

namespace App\Models\Scopes;

use Vietiso\Core\Database\Model\Scopes\Scope;
use Vietiso\Core\Database\Model\Builder;
use Vietiso\Core\Database\Model\Model;

class ActiveScope implements Scope
{
public function apply(Builder $builder, Model $model): void
{
$builder->where('is_active', true);
}
}
<?php

namespace App\Models;

use Vietiso\Core\Database\Model\Model;
use Vietiso\Core\Database\Attributes\GlobalScope;
use App\Models\Scopes\ActiveScope;

#[GlobalScope(ActiveScope::class)]
class User extends Model
{
}
// Query tự động thêm WHERE is_active = true
$users = User::get();

// Bỏ global scope
$users = User::withoutGlobalScope(ActiveScope::class)->get();

// Bỏ nhiều global scopes
$users = User::withoutGlobalScopes([
ActiveScope::class,
AnotherScope::class,
])->get();

Local Scopes

<?php

namespace App\Models;

use Vietiso\Core\Database\Model\Model;
use Vietiso\Core\Database\Attributes\Scope;
use Vietiso\Core\Database\Model\Builder;

class User extends Model
{
#[Scope]
public function scopeActive(Builder $query): Builder
{
return $query->where('is_active', true);
}

#[Scope]
public function scopeRole(Builder $query, string $role): Builder
{
return $query->where('role', $role);
}
}
// Sử dụng scopes
$users = User::active()->get();
$admins = User::active()->role('admin')->get();

Model Events

<?php

namespace App\Models;

use Vietiso\Core\Database\Model\Model;
use Vietiso\Core\Database\Attributes\Event;

class User extends Model
{
#[Event('creating')]
public static function onCreating(User $user): void
{
$user->uuid = generate_uuid();
}

#[Event('created')]
public static function onCreated(User $user): void
{
// Gửi email chào mừng
}

#[Event('updating')]
public static function onUpdating(User $user): void
{
// Trước khi update
}

#[Event('updated')]
public static function onUpdated(User $user): void
{
// Sau khi update
}

#[Event('deleting')]
public static function onDeleting(User $user): void
{
// Trước khi delete
}

#[Event('deleted')]
public static function onDeleted(User $user): void
{
// Sau khi delete
}
}

Hidden & Visible Attributes

<?php

namespace App\Models;

use Vietiso\Core\Database\Model\Model;

class User extends Model
{
// Ẩn khi serialize (toArray, toJson)
protected array $hidden = ['password', 'remember_token'];

// Hoặc chỉ hiện các fields này
protected array $visible = ['id', 'name', 'email'];
}

Serialization

$user = User::find(1);

// Chuyển thành array
$array = $user->toArray();

// Chuyển thành JSON
$json = $user->toJson();

// Tự động serialize khi return trong controller
return $user; // Trả về JSON