Laravel Eloquent 技巧与窍门:每位专业开发者都应了解

发布: (2026年2月6日 GMT+8 19:53)
4 分钟阅读
原文: Dev.to

Source: Dev.to

Laravel Eloquent 是 PHP 生态系统中最强大且表达力十足的 ORM 系统之一。然而,大多数开发者只触及了 Eloquent 的表面。本文涵盖了专业开发者在编写更清晰、更快、更具可扩展性的应用时使用的高级 Laravel Eloquent 技巧和最佳实践。

避免 N+1 查询问题

// Bad Practice
$posts = Post::all();
foreach ($posts as $post) {
    echo $post->user->name;
}

上述代码会为每篇文章的用户触发一次单独的查询。

// Best Practice
$posts = Post::with('user')->get();

预加载(Eager loading)显著减少数据库查询次数并提升性能。

只选择需要的列

// Bad Practice
User::all();

获取不必要的列会增加内存使用并拖慢查询。

// Best Practice
User::select('id', 'name', 'email')->get();

始终只获取实际需要的数据。

使用 Chunk 分块处理大数据集

// Bad Practice (may exhaust memory)
User::all();
// Best Practice
User::chunk(100, function ($users) {
    foreach ($users as $user) {
        // process user
    }
});

Chunk 分块可以保持低内存占用,适用于后台任务和定时任务。

处理复杂关系

Laravel 支持高级关系类型,如 hasOneThroughhasManyThrough 和多态关系。

public function comments()
{
    return $this->morphMany(Comment::class, 'commentable');
}

这些关系有助于保持数据库设计的简洁和可扩展性。

使用查询作用域提升可复用性

// Usage
User::active()->admin()->get();

public function scopeActive($query)
{
    return $query->where('status', 'active');
}

作用域让查询更易读且可复用。

防止批量赋值漏洞

// Bad Practice
User::create($request->all());
// Best Practice
protected $fillable = ['name', 'email'];
// or
protected $guarded = ['is_admin'];

定义 $fillable$guarded 可以防止未授权的数据修改。

高效的存在性检查

// Bad Practice
User::where('email', $email)->count();
// Best Practice
User::where('email', $email)->exists();

exists() 在找到匹配项后立即停止查询,速度更快。

在不加载关系的情况下统计数量

// Bad Practice
$post->comments->count();
// Best Practice
Post::withCount('comments')->get();

withCount 避免加载整个关系数据。

批量更新

// Bad Practice
$user = User::find($id);
$user->status = 'active';
$user->save();
// Best Practice
User::where('id', $id)->update(['status' => 'active']);

这可以减少数据库查询次数。

使用 firstOrCreate 防止竞争条件

User::firstOrCreate(
    ['email' => $email],
    ['name' => $name]
);

这些方法简化逻辑并防止竞争条件。

属性类型转换

protected $casts = [
    'is_active' => 'boolean',
    'settings'   => 'array',
    'email_verified_at' => 'datetime',
];

类型转换确保整个应用的数据类型保持一致。

隐藏敏感属性

protected $hidden = [
    'password',
    'remember_token',
];

隐藏这些字段对于 API 安全至关重要。

对关键操作使用数据库事务

DB::transaction(function () {
    Order::create([...]);
    Payment::create([...]);
});

事务可以防止数据出现部分写入的情况。

监控查询以发现性能瓶颈

DB::listen(function ($query) {
    logger($query->sql);
});

定期的查询监控有助于及早发现性能问题。

Back to Blog

相关文章

阅读更多 »