You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将行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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 02:37:44