将行SQL查询转换为Laravel Eloquent查询及关联查询实现方法
解决方案说明
一、先定义模型关联
先假设你的表结构为(如果和实际不符,自行调整关联字段即可):
users表:主键id,存储用户信息orders表:外键user_id关联users.id,外键product_id关联products.id,存储订单信息products表:主键id,存储商品信息
对应模型的关联代码如下:
User模型(app/Models/User.php)
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; class User extends Model { // 用户拥有多个订单 public function orders(): HasMany { return $this->hasMany(Order::class); } }
Order模型(app/Models/Order.php)
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; class Order extends Model { // 订单属于一个用户 public function user(): BelongsTo { return $this->belongsTo(User::class); } // 订单属于一个商品 public function product(): BelongsTo { return $this->belongsTo(Product::class); } }
Product模型(app/Models/Product.php)
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; class Product extends Model { // 商品被多个订单关联 public function orders(): HasMany { return $this->hasMany(Order::class); } }
二、SQL转Eloquent查询
假设你的原SQL是类似这样的多表关联查询:
SELECT users.name, orders.order_no, products.title, orders.created_at FROM orders INNER JOIN users ON orders.user_id = users.id INNER JOIN products ON orders.product_id = products.id WHERE orders.status = 'paid' AND orders.created_at >= '2024-01-01' ORDER BY orders.created_at DESC
对应的Eloquent查询写法如下:
use App\Models\Order; $results = Order::select('users.name', 'orders.order_no', 'products.title', 'orders.created_at') ->join('users', 'orders.user_id', '=', 'users.id') ->join('products', 'orders.product_id', '=', 'products.id') ->where('orders.status', 'paid') ->where('orders.created_at', '>=', '2024-01-01') ->orderBy('orders.created_at', 'desc') ->get();
三、单条Eloquent关联查询(预加载实现)
如果不想手动写join,可以用Laravel的**预加载(Eager Loading)**通过关联关系实现查询,还能避免N+1查询问题,有两种常见写法:
写法1:从订单出发,预加载关联的用户和商品
$orders = Order::with(['user', 'product']) ->where('status', 'paid') ->where('created_at', '>=', '2024-01-01') ->orderBy('created_at', 'desc') ->get(); // 遍历获取数据示例 foreach ($orders as $order) { echo $order->user->name; // 关联用户的名称 echo $order->product->title;// 关联商品的标题 echo $order->order_no; // 订单编号 }
写法2:从用户出发,关联订单及对应商品
$users = User::with(['orders' => function ($query) { // 筛选符合条件的订单,并预加载关联的商品 $query->where('status', 'paid') ->where('created_at', '>=', '2024-01-01') ->orderBy('created_at', 'desc') ->with('product'); }])->get(); // 遍历获取数据示例 foreach ($users as $user) { foreach ($user->orders as $order) { echo $user->name; echo $order->product->title; echo $order->order_no; } }
四、关键注意点
- 如果你的外键不是Laravel默认规则(比如订单表用
customer_id关联用户表的id),需要在关联方法里指定外键:return $this->belongsTo(User::class, 'customer_id'); - 若只需获取关联表的特定字段,可这样写:
with(['user:id,name', 'product:id,title']),必须包含关联外键字段(比如用户表的id),否则无法建立关联 - 预加载时,用闭包可以对关联模型添加筛选、排序条件,灵活度很高
内容的提问来源于stack exchange,提问作者Sahil Rana
相关产品推荐
相关产品推荐

