Laravel - 如何在预加载的多态关系中按字段对查询进行排序?

Laravel - How can I order a query by a field in an eager loaded polymorphic relationship?

我在用户和承包商之间设置了多态关系:

Schema::create('users', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->string('first_name');
    $table->string('last_name');
    $table->morphs('user');
});

Schema::create('contractors', function (Blueprint $table) {
    $table->bigIncrements('id');
    //... etc
});

App\User

public function userable()
{
    return $this->morphTo();
}

App\Contractor

public function user()
{
    return $this->morphOne('App\User', 'userable');
}

目标是拥有不同的用户类型,因为承包商可能有我们需要收集的其他字段数据,但他们将始终拥有用户中的所有字段 table。

我遇到的问题是,当获取所有承包商并急切加载用户数据时,如何按用户 table 中的 last_name 列进行排序?

class ContractorController extends Controller
{
    public function all(Request $request)
    {
        return Contractor::with('user')->paginate(15); // order by users.last_name here
    }
}

我读到我必须加入 tables,但由于某种原因在响应中为用户对象返回 NULL。

class ContractorController extends Controller
{
    public function all(Request $request)
    {
        return Contractor::with('user')
            ->join('users', 'contractors.id', '=', 'users.userable_id')
            ->paginate(15);
    }
}

因为lastname是用户table这一列。您不能使用 with('user') 并按 lastname 排序。

但是,您可以使用 join('users',...) 而不是 with(user):

Contractor::join('users', 'contractors.id', '=', 'users.userable_id')
          ->orderBy('users.lastname')
          ->paginate(15);

而且因为在使用join的时候有重复的id(contractors.id, users.id),如果你还想获取user对象作为属性,可以这样:

Contractor::join('users', 'contractors.id', '=', 'users.userable_id')
          ->orderBy('users.lastname')
          ->selectRaw('contractors.*, users.lastname')
          ->with('user')
          ->paginate(15);