Eloquent Best Practices

iSerter/laravel-claude-agents/skills/eloquent-best-practices

作者 iSerter8868214ee3fe0eee4e865dd07dbb9832a05b6ddc無授權條款收錄於 2026年10月9日更新於 2026年10月9日

Best practices for Laravel Eloquent ORM including query optimization, relationship management, and avoiding common pitfalls like N+1 queries.

AI 產生的概覽

關於 Laravel Eloquent ORM 最佳實務的指引,涵蓋查詢最佳化、關聯管理與避免 N+1 查詢。

功能
此技能提供撰寫高效 Laravel Eloquent ORM 程式碼的參考指引與程式碼範例。內容涵蓋預先載入、欄位選擇、查詢範圍、關聯回傳型別、withCount、大量指派保護、型別轉換、分塊處理、資料庫層級操作、模型事件、索引,以及防止延遲載入。它產出說明性程式碼片段與檢查清單,而非可執行指令碼。
適用情境
適用於處理 Laravel Eloquent 模型與查詢時,尤其是最佳化效能、修正 N+1 查詢問題,或檢視關聯與大量指派模式。也適合在審查以 Eloquent 為基礎的程式碼時作為檢查清單使用。
執行需求
不需要指令碼或特殊工具,僅為說明與程式碼範例。假定使用搭載 Eloquent 的 Laravel 專案。

Eloquent Best Practices

Query Optimization

Always Eager Load Relationships

php
// ❌ N+1 Query Problem$posts = Post::all();foreach ($posts as $post) {    echo $post->user->name; // N additional queries}
// ✅ Eager Loading$posts = Post::with('user')->get();foreach ($posts as $post) {    echo $post->user->name; // No additional queries}

Select Only Needed Columns

php
// ❌ Fetches all columns$users = User::all();
// ✅ Only needed columns$users = User::select(['id', 'name', 'email'])->get();
// ✅ With relationships$posts = Post::with(['user:id,name'])->select(['id', 'title', 'user_id'])->get();

Use Query Scopes

php
// ✅ Define reusable query logicclass Post extends Model{    public function scopePublished($query)    {        return $query->where('status', 'published')                    ->whereNotNull('published_at');    }        public function scopePopular($query, $threshold = 100)    {        return $query->where('views', '>', $threshold);    }}
// Usage$posts = Post::published()->popular()->get();

Relationship Best Practices

Define Return Types

php
use Illuminate\Database\Eloquent\Relations\BelongsTo;use Illuminate\Database\Eloquent\Relations\HasMany;
class Post extends Model{    public function user(): BelongsTo    {        return $this->belongsTo(User::class);    }        public function comments(): HasMany    {        return $this->hasMany(Comment::class);    }}

Use withCount for Counts

php
// ❌ Triggers additional queriesforeach ($posts as $post) {    echo $post->comments()->count();}
// ✅ Load counts efficiently$posts = Post::withCount('comments')->get();foreach ($posts as $post) {    echo $post->comments_count;}

Mass Assignment Protection

php
class Post extends Model{    // ✅ Whitelist fillable attributes    protected $fillable = ['title', 'content', 'status'];        // Or blacklist guarded attributes    protected $guarded = ['id', 'user_id'];        // ❌ Never do this    // protected $guarded = [];}

Use Casts for Type Safety

php
class Post extends Model{    protected $casts = [        'published_at' => 'datetime',        'metadata' => 'array',        'is_featured' => 'boolean',        'views' => 'integer',    ];}

Chunking for Large Datasets

php
// ✅ Process in chunks to save memoryPost::chunk(200, function ($posts) {    foreach ($posts as $post) {        // Process each post    }});
// ✅ Or use lazy collectionsPost::lazy()->each(function ($post) {    // Process one at a time});

Database-Level Operations

php
// ❌ Slow - loads into memory first$posts = Post::where('status', 'draft')->get();foreach ($posts as $post) {    $post->update(['status' => 'archived']);}
// ✅ Fast - single queryPost::where('status', 'draft')->update(['status' => 'archived']);
// ✅ Increment/decrementPost::where('id', $id)->increment('views');

Use Model Events Wisely

php
class Post extends Model{    protected static function booted()    {        static::creating(function ($post) {            $post->slug = Str::slug($post->title);        });                static::deleting(function ($post) {            $post->comments()->delete();        });    }}

Common Pitfalls to Avoid

Don't Query in Loops

php
// ❌ Badforeach ($userIds as $id) {    $user = User::find($id);}
// ✅ Good$users = User::whereIn('id', $userIds)->get();

Don't Forget Indexes

php
// MigrationSchema::create('posts', function (Blueprint $table) {    $table->id();    $table->foreignId('user_id')->constrained()->index();    $table->string('slug')->unique();    $table->string('status')->index();    $table->timestamp('published_at')->nullable()->index();        // Composite index for common queries    $table->index(['status', 'published_at']);});

Prevent Lazy Loading in Development

php
// In AppServiceProvider boot methodModel::preventLazyLoading(!app()->isProduction());

Checklist

  • Relationships eagerly loaded where needed
  • Only selecting required columns
  • Using query scopes for reusability
  • Mass assignment protection configured
  • Appropriate casts defined
  • Indexes on foreign keys and query columns
  • Using database-level operations when possible
  • Chunking for large datasets
  • Model events used appropriately
  • Lazy loading prevented in development

來源與署名

來源:iSerter/laravel-claude-agents位於skills/eloquent-best-practices提交8868214

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架