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

Laravel中如何获取指定订阅对应的首个订单?

解决Laravel中获取客户订阅对应首个订单的问题

模型结构

Order:
- id
- amount
- plan_id
- client_id (注:根据关联代码推断模型存在该字段)

Plan:
- id
- name
- price

Subscription:
- id
- plan_id
- starts_at
- ends_at
- subscriber_type
- subscriber_id

Client:
- id
- name

其中subscriber_type固定为App\Models\Client,subscriber_id关联客户ID。

现有模型关联代码

Plan.php

class Plan extends Model implements Sortable
{  
    public function subscriptions(): HasMany
    {
        return $this->hasMany(Subscription::class);
    }

    public function orders(): HasMany
    {
        return $this->hasMany(Order::class);
    }
    // 其他代码...
}

Subscription.php

class Subscription extends Model{
    public function plan(): BelongsTo
    {
        return $this->belongsTo(Plan::class);
    }
}

Client.php

class Client extends Model{
    public function subscriptions(): MorphMany
    {
        return $this->morphMany(Subscription::class, 'subscriber', 'subscriber_type', 'subscriber_id');
    }
}

Order.php

class Order extends Model
{
    use HasFactory;

    public function client(): BelongsTo
    {
        return $this->belongsTo(Client::class);
    }           
}

需求与问题

创建订阅时会同步生成对应plan_id的订单。现在需要获取某客户的所有订阅时,同时拿到每个订阅对应的该客户的首个订单。

尝试过两种方法,但都存在问题:

  1. 第一种方法返回了该套餐下该客户的所有订单,不符合仅需首个订单的需求:
$client->subscriptions()->with(['plan.orders' => function ($query) use ($client) {
    $query->where('client_id', $client->id)
          ->orderBy('created_at');
}]);
  1. 第二种方法仅首个订阅结果中返回了订单,后续订阅的orders为空数组:
$client->subscriptions()->with(['plan.orders' => function ($query) use ($client) {
    $query->where('client_id', $client->id)
          ->orderBy('created_at')
          ->first();
}]);

解决方案

方案一:调整关联查询约束

问题出在使用->first(),它会直接执行查询并返回单个模型,导致后续订阅的关联查询复用了空结果。改用->limit(1)来约束每个关联仅返回第一条记录:

$subscriptions = $client->subscriptions()->with(['plan.orders' => function ($query) use ($client) {
    $query->where('client_id', $client->id)
          ->orderBy('created_at')
          ->limit(1);
}])->get();

此时每个订阅的plan.orders会是一个仅包含首个订单的集合。

方案二:给Subscription添加专属关联

如果需要更直观地获取单个订单模型,可以在Subscription模型中定义一个直接关联到对应首个订单的hasOne关联:

// Subscription.php
public function firstOrder(): HasOne
{
    return $this->hasOne(Order::class, 'plan_id', 'plan_id')
                ->where('client_id', $this->subscriber_id)
                ->orderBy('created_at');
}

使用时直接关联该字段即可:

$subscriptions = $client->subscriptions()->with('firstOrder')->get();

每个订阅的firstOrder字段会直接返回对应的首个订单模型,无需嵌套到plan下。


内容的提问来源于stack exchange,提问作者DeveloperX

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 08:03:29