Eloquent Model
File:
packages/skilldo/framework/src/Database/Eloquent/Model.php
Namespace:SkillDo\Database\Eloquent\Model
Tài liệu tham khảo: Laravel Eloquent
1. Eloquent Model là gì?
Eloquent là một ORM (Object-Relational Mapper) - giúp bạn làm việc với bảng Database thông qua các đối tượng PHP (class) thay vì viết SQL thuần.
Class SkillDo\Database\Eloquent\Model là phiên bản tùy chỉnh của Eloquent được SkillDo CMS v8 xây dựng lại để bổ sung thêm các tính năng đặc thù như:
- ModelEvents (Hooks tự động:
saving,saved,deleted...) - ModelMeta (Hỗ trợ bảng metadata)
- SoftDeletes (Xóa mềm với cột
trash) - ModelRoute (Tự động quản lý URL/Slug)
- ModelLanguage (Đa ngôn ngữ)
2. Tạo Model cho Plugin
Bước 1: Khai Báo Class Model
Tạo file đặt trong app/Models/ của Plugin:
<?php
namespace MyPlugin\Models;
use SkillDo\Database\Eloquent\Model;
class Booking extends Model
{
// Tên bảng trong database (bắt buộc)
protected string $table = 'bookings';
// Khai báo danh sách cột và kiểu dữ liệu của chúng
// Đây là đặc điểm riêng của SkillDo Model (khác Laravel)
protected array $columns = [
'name' => ['string'],
'phone' => ['string'],
'service_id' => ['int', 0], // [kiểu, giá_trị_mặc_định]
'status' => ['int', 1],
'note' => ['string'],
];
}
Bước 2: Đăng Ký Alias (Tùy Chọn)
Mở file bootstrap/config.php của Plugin và đăng ký alias để dùng ngắn gọn:
// Trong bootstrap/config.php
app()->alias('Booking', \MyPlugin\Models\Booking::class);
// Sau đó có thể dùng
$bookings = Booking::where('status', 1)->get();
3. Các Thao Tác CRUD Cơ Bản
3.1 L ấy Dữ Liệu (Read)
use MyPlugin\Models\Booking;
// Lấy tất cả
$bookings = Booking::all();
// Lấy bản ghi với điều kiện
$activeBookings = Booking::where('status', 1)->get();
// Lấy một bản ghi theo ID
$booking = Booking::find(5);
echo $booking->name;
// Lấy bản ghi đầu tiên khớp điều kiện
$booking = Booking::where('phone', '0901234567')->first();
// Đếm số lượng
$count = Booking::where('status', 1)->count();
3.2 Thêm Mới (Create)
Bạn có hai cách:
Cách 1: Dùng create() trên Query Builder (khuyến nghị)
$bookingId = Booking::create([
'name' => 'Nguyễn Văn A',
'phone' => '0901234567',
'service_id' => 3,
'status' => 1,
'note' => 'Yêu cầu đặc biệt...',
]);
if (is_skd_error($bookingId)) {
// Xử lý lỗi
echo $bookingId->first();
} else {
echo "Tạo thành công, ID = " . $bookingId;
}
Cách 2: Tạo instance rồi gọi save()
$booking = new Booking();
$booking->name = 'Nguyễn Văn A';
$booking->phone = '0901234567';
$booking->service_id = 3;
$booking->status = 1;
// Model sẽ nhận biết đây là INSERT (vì chưa có ID)
$result = $booking->save();
3.3 Cập Nhật (Update)
Cách 1: Lấy bản ghi rồi sửa
$booking = Booking::find(5);
$booking->status = 2;
$booking->note = 'Đã xác nhận';
$booking->save(); // Model nhận biết là UPDATE (vì đã có ID)
Cách 2: Mass update qua Query Builder
Booking::where('status', 0)
->where('created', '<', '2026-01-01')
->update(['status' => 3]); // Cập nhật tất cả khớp điều kiện
3.4 Xóa (Delete)
// Lấy bản ghi rồi xóa
$booking = Booking::find(5);
$booking->delete();
// Xóa theo điều kiện (hàng loạt)
Booking::where('status', 3)->delete();
// Xóa theo ID cụ thể
Booking::whereIn('id', [1, 2, 3])->delete();
4. Model Events (Hooks Tự Động)
Model của SkillDo hỗ trợ các hook lắng nghe sự kiện được khai báo trong boot(). Đây là tính năng rất mạnh để tự động hóa logic khi lưu/xóa dữ liệu.
class Booking extends Model
{
protected string $table = 'bookings';
protected static function boot(): void
{
parent::boot();
// Chạy TRƯỚC khi lưu (cả insert lẫn update)
static::saving(function (Booking $booking) {
// Chuẩn hóa số điện thoại trước khi lưu
$booking->phone = preg_replace('/\D/', '', $booking->phone);
});
// Chạy SAU khi lưu thành công
static::saved(function (Booking $booking, $action) {
// $action = 'add' (thêm mới) | 'update' (cập nhật)
if ($action === 'add') {
// Gửi email thông báo đặt lịch mới
// NotificationService::sendBookingConfirmation($booking);
}
});
// Chạy SAU khi xóa thành công
static::deleted(function (Booking $booking, $listIdRemove, $objects) {
// Dọn dẹp dữ liệu liên quan
\Illuminate\Support\Facades\DB::table('booking_services')
->whereIn('booking_id', $listIdRemove)
->delete();
});
}
}
Danh sách Events hỗ trợ:
| Event | Thời điểm kích hoạt |
|---|---|
saving | Trước khi lưu (Insert hoặc Update) |
saved | Sau khi lưu thành công |
creating | Trước khi Insert mới |
created | Sau khi Insert thành công |
updating | Trước khi Update |
updated | Sau khi Update thành công |
deleting | Trước khi Delete |
deleted | Sau khi Delete thành công |
retrieved | Sau khi bản ghi được load từ DB |
5. Query Scopes (Phạm Vi Truy Vấn Tùy Biến)
Scope giúp bạn đóng gói các điều kiện WHERE phức tạp thành một phương thức gọi dễ đọc.
class Booking extends Model
{
// Định nghĩa Local Scope
// Tên hàm luôn bắt đầu bằng tiền tố 'scope'
public function scopeActive($query)
{
return $query->where('status', 1);
}
public function scopeByService($query, $serviceId)
{
return $query->where('service_id', $serviceId);
}
}
// Cách gọi (KHÔNG cần viết 'scope', gọi trực tiếp tên sau tiền tố):
$bookings = Booking::active()->get();
$bookings = Booking::active()->byService(3)->orderBy('created', 'desc')->get();
6. Relationships (Quan Hệ Giữa Các Bảng)
SkillDo Model hỗ trợ các loại quan hệ Eloquent cơ bản:
hasMany (Một-Nhiều)
class User extends Model
{
public function bookings(): \SkillDo\Database\Eloquent\Relations\HasMany
{
// User có nhiều Booking (dựa trên cột 'user_created' trong bảng bookings)
return $this->hasMany(Booking::class, 'user_created', 'id');
}
}
// Lấy user kèm danh sách booking (Eager Loading - tránh N+1)
$users = User::with('bookings')->get();
foreach ($users as $user) {
foreach ($user->bookings as $booking) {
echo $booking->name;
}
}