1.1 在 Laravel 项目的开发中,多态的需求很常见,按多态关联进行排序的需求也是必须的。

1.2 请想像,我们有一个需求,荣誉栏目多态关联一个档案模型,要求在荣誉中按档案的推荐时间进行排序,以获取最近推荐内容的前5条。

2.1 Honour

<?php
namespace App;
use App\Traits\HasArchive;
use Illuminate\Database\Eloquent\Model;
class Honour extends BaseModel
    use HasArchive;
    protected static function boot()
        parent::boot();
        static::created(function ($honour) {
            info(__CLASS__ . __METHOD__);

2.2 HasArchive

<?php
namespace App\Traits;
use App\Archive;
trait HasArchive
     * The boot method.
    public static function bootHasArchive()
         * Handle the "deleting" event.
        static::deleting(function ($model) {
            $class = get_class($model);
            info("HasArchive Trait deleting {$class} {$model->id}");
            if ($archive = $model->archive) {
                $archive->delete();
        static::created(function ($model) {
            info(__CLASS__ . __METHOD__);
     * Model has an archive.
     * @return mixed
    public function archive()
        return $this->morphOne(Archive::class, 'model_has_archive');
     * Scope of params.
     * @param $query
     * @param array $params
     * @return mixed
    public function scopeOfParams($query, $params = [])
        $field   = null;
        $keyword = null;
        $sort    = null;
        $order   = null;
        extract($params);
        $class = $this->getMorphClass();
        $table = $this->getTable();
        $query->leftJoin('archives', 'archives.model_has_archive_id', '=', "{$table}.id")
            ->where('archives.model_has_archive_type', $class)
            ->select(["{$table}.*"]);
        if ($keyword) {
            if ($field) {
                $query->where(function ($query) use ($field, $keyword) {
                    $query->orWhere($field, 'regexp', $keyword);
            } else {
                $query->where(function ($query) use ($keyword) {
                    foreach (['archives.title', 'archives.title_pinyin'] as $field) {
                        $query->orWhere($field, 'regexp', $keyword);
        if ($sort && $order) {
            $query->orderBy($sort, $order);
        return $query;
     * Scope recommended.
     * @param $query
     * @return mixed
    public function scopeRecommended($query)
        return $query->whereHas('archive', function ($query) {
            return $query->recommended();

2.3 测试通过

3.1 可以通过 leftJoin 多表关联,之后排序