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

Laravel 9 多态关联排序:按example_data的external键值排序Example模型

问题描述

现有如下表结构:

-- table: examples
+ -- + ---- +
| id | name |
+ -- + ---- +
| 1  | Test |
| 2  | Test |
+ -- + ---- +

-- table: example_data
+ -- + --------------- + ------------------ + ---------- + --------- +
| id | example_data_id | exmaple_data_type  | key        | value     |
+ -- + --------------- + ------------------ + ---------- + --------- +
| 1  | 1               | App\Models\Example | external   | 1         |
| 2  | 1               | App\Models\Example | otherKey   | string    |
| 3  | 2               | App\Models\Example | external   | 0         |
+ -- + --------------- + ------------------ + ---------- + --------- +

模型代码:

// Example Model:
public function daten()
{
    return $this->morphMany(ExampleData::class, 'example_data');
}

// ExampleData Model:
public function example_data()
{
    return $this->morphTo();
}

需求:按example_data表中key为"external"对应的value字段对Example模型数据进行排序,现有查询代码如下:

$examples = Example::with('daten')
                    ->orderBy(***value from external in daten***)  // 期望实现:Example->daten中key="external"时,按对应的value排序
                    ->paginate($request->total);

请问是否可以使用orderBy结合回调实现该需求?如果可以,对应的回调写法是怎样的?


解决方案

直接通过orderBy结合回调无法实现该需求,因为orderBy是数据库层面的排序逻辑,回调无法直接关联到关联模型的特定字段。可以通过以下两种方式实现:

方法一:数据库关联排序(推荐,支持原生分页)

通过join关联example_data表,筛选出key='external'的记录后按value排序:

$examples = Example::with('daten')
    ->join('example_data', function ($join) {
        $join->on('examples.id', '=', 'example_data.example_data_id')
             ->where('example_data.exmaple_data_type', '=', 'App\Models\Example')
             ->where('example_data.key', '=', 'external');
    })
    ->orderBy('example_data.value')
    ->select('examples.*') // 避免关联表字段冲突
    ->paginate($request->total);

若单个Example对应多条key='external'的example_data记录,需追加->groupBy('examples.id')避免数据重复。

方法二:集合层面排序(适合小数据量,分页需手动处理)

先查询所有数据,再在Eloquent集合中通过回调排序:

// 先获取全部数据并预加载关联
$examples = Example::with('daten')->get();

// 按external的value排序
$sortedExamples = $examples->sortBy(function ($example) {
    $externalItem = $example->daten->where('key', 'external')->first();
    return $externalItem ? $externalItem->value : 0; // 无数据时用默认值0排序
});

// 手动实现分页,需引入LengthAwarePaginator
use Illuminate\Pagination\LengthAwarePaginator;

$currentPage = LengthAwarePaginator::resolveCurrentPage();
$perPage = $request->total;
$paginatedExamples = new LengthAwarePaginator(
    $sortedExamples->forPage($currentPage, $perPage),
    $sortedExamples->count(),
    $perPage,
    $currentPage,
    ['path' => LengthAwarePaginator::resolveCurrentPath()]
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 03:10:14