Chuyển đến nội dung chính

第 4 課:雄辯的 ORM 和關係

雄辯的模型、批次分配、軟刪除。關係式(hasOne、hasMany、belongsTo、belongsToMany、morphMany)。預先載入、查詢範圍、存取器/修改器。演員表。

💻 程式設計 — 第 4 課 第 4 課:雄辯的 ORM 和關係

Laravel:從基礎到高級

第 1 部分:Laravel 基礎知識

亞洲開發網

1. 雄辯模型

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Casts\Attribute;

class Product extends Model
{
    use SoftDeletes;

    protected $fillable = ['name', 'slug', 'description', 'price', 'stock', 'category_id'];

    protected function casts(): array
    {
        return [
            'price' => 'decimal:2',
            'is_active' => 'boolean',
            'metadata' => 'array',
            'published_at' => 'datetime',
        ];
    }

    // Accessor (Laravel 11)
    protected function formattedPrice(): Attribute
    {
        return Attribute::make(
            get: fn () => number_format($this->price) . 'đ',
        );
    }
}

2. 關係

class Product extends Model
{
    // One-to-Many
    public function category()
    {
        return $this->belongsTo(Category::class);
    }

    public function reviews()
    {
        return $this->hasMany(Review::class);
    }

    // Many-to-Many
    public function tags()
    {
        return $this->belongsToMany(Tag::class)->withTimestamps();
    }

    // Has One Through
    public function brandCountry()
    {
        return $this->hasOneThrough(Country::class, Brand::class);
    }

    // Polymorphic
    public function images()
    {
        return $this->morphMany(Image::class, 'imageable');
    }
}

// Sử dụng
$product->category->name;
$product->tags()->attach([1, 2, 3]);
$product->tags()->sync([1, 2]);

3. 預加載

// N+1 prevention
$products = Product::with(['category', 'tags', 'reviews.user'])->get();

// Conditional eager loading
$products = Product::with(['reviews' => function ($query) {
    $query->where('rating', '>=', 4)->latest()->limit(5);
}])->get();

// Lazy eager loading
$products = Product::all();
$products->load('category');

// Prevent N+1 (development)
// AppServiceProvider
Model::preventLazyLoading(!app()->isProduction());

4. 查詢範圍

class Product extends Model
{
    // Local scope
    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    public function scopePriceRange($query, float $min, float $max)
    {
        return $query->whereBetween('price', [$min, $max]);
    }
}

// Sử dụng
$products = Product::active()->priceRange(100, 500)->paginate(20);

下一篇: 遷移、播種和查詢產生器。