本文目录导读:

在Laravel中,使用Eloquent ORM处理数据库关联关系确实可以非常优雅,以下是一些最佳实践和示例:
基础关联关系定义
一对一关系 (One-to-One)
class User extends Model
{
public function profile()
{
return $this->hasOne(Profile::class);
}
}
class Profile extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
}
// 使用
$profile = User::find(1)->profile;
$user = Profile::find(1)->user;
一对多关系 (One-to-Many)
class Post extends Model
{
public function comments()
{
return $this->hasMany(Comment::class);
}
}
class Comment extends Model
{
public function post()
{
return $this->belongsTo(Post::class);
}
}
// 使用
$comments = Post::find(1)->comments;
多对多关系 (Many-to-Many)
class User extends Model
{
public function roles()
{
return $this->belongsToMany(Role::class)
->withPivot('expires_at')
->withTimestamps();
}
}
class Role extends Model
{
public function users()
{
return $this->belongsToMany(User::class);
}
}
// 使用
$user->roles()->attach($roleId); // 添加关系
$user->roles()->detach($roleId); // 移除关系
$user->roles()->sync([1, 2, 3]); // 同步关系
高级关联技巧
远程一对多 (Has Many Through)
class Country extends Model
{
public function posts()
{
return $this->hasManyThrough(
Post::class, // 最终要获取的模型
User::class, // 中间模型
'country_id', // 用户表中的外键
'user_id', // 文章表中的外键
'id', // 国家表本地键
'id' // 用户表本地键
);
}
}
多态关联 (Polymorphic Relations)
class Comment extends Model
{
public function commentable()
{
return $this->morphTo();
}
}
class Post extends Model
{
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
}
class Video extends Model
{
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
}
// 使用
$post = Post::find(1);
$comments = $post->comments; // 获取文章的所有评论
预加载优化 (Eager Loading)
// 基本预加载
$users = User::with('posts.comments')->get();
// 条件预加载
$users = User::with(['posts' => function ($query) {
$query->where('is_published', true);
}])->get();
// 预加载特定字段
$users = User::with('profile:id,user_id,avatar')->get();
// 延迟预加载
$users = User::all();
$users->load('posts.comments');
// 统计关联数量
$users = User::withCount('posts')->get();
关联操作
创建关联
// 方法1:创建新记录
$user = User::find(1);
$post = $user->posts()->create([ => '新文章',
'content' => '内容'
]);
// 方法2:关联已存在的记录
$user->posts()->associate($post);
// 方法3:多对多关联
$user->roles()->attach($roleId, ['expires_at' => now()]);
$user->roles()->toggle([1, 2, 3]); // 切换关联
查询关联
// 条件关联查询
$posts = Post::whereHas('comments', function ($query) {
$query->where('is_approved', true);
})->get();
// 条件关联不存在查询
$users = User::whereDoesntHave('posts')->get();
// 复合条件
$users = User::with(['posts' => function ($query) {
$query->where('created_at', '>', now()->subMonth());
}])->get();
关联自定义
自定义关联键名
class User extends Model
{
public function posts()
{
return $this->hasMany(Post::class, 'author_id', 'local_key');
}
}
软删除关联
class Post extends Model
{
use SoftDeletes;
public function comments()
{
return $this->hasMany(Comment::class);
}
}
// 包含软删除的关联
$post = Post::withTrashed()->find(1);
$comments = $post->comments()->withTrashed()->get();
实例应用场景
电子商务系统示例
class Order extends Model
{
public function items()
{
return $this->hasMany(OrderItem::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
public function payments()
{
return $this->hasMany(Payment::class);
}
public function latestPayment()
{
return $this->hasOne(Payment::class)->latestOfMany();
}
}
// 复杂查询示例
$orders = Order::with([
'user' => function ($query) {
$query->select('id', 'name', 'email');
},
'items.product',
'latestPayment'
])
->where('status', 'pending')
->where('created_at', '>', now()->subDays(7))
->get();
性能优化技巧
// 使用延迟关联加载
$users = User::all();
$users->loadMissing(['posts', 'profile']); // 只加载未加载的关联
// 关联计数
$users = User::withCount(['posts', 'comments'])->get();
// 子查询优化
$users = User::select('users.*')
->selectSub(function ($query) {
$query->from('posts')
->whereRaw('posts.user_id = users.id')
->selectRaw('count(*)');
}, 'posts_count')
->get();
这些技巧能帮助你更优雅地处理数据库关联关系,既保持了代码的简洁性,又获得了良好的性能,记得根据具体场景合理选择不同的关联方式和优化策略。