ChatGPT解决这个技术问题 Extra ChatGPT

Laravel orderBy 关系

我正在遍历特定帖子的作者发布的所有评论。

foreach($post->user->comments as $comment)
{
    echo "<li>" . $comment->title . " (" . $comment->post->id . ")</li>";
}

这给了我

I love this post (3)
This is a comment (5)
This is the second Comment (3)

我将如何按 post_id 排序,以便将上述列表排序为 3、3、5


R
Rob Gordijn

可以使用查询函数扩展关系:

<?php
public function comments()
{
    return $this->hasMany('Comment')->orderBy('column');
}

[评论后编辑]

<?php
class User
{
    public function comments()
    {
        return $this->hasMany('Comment');
    }
}

class Controller
{
    public function index()
    {
        $column = Input::get('orderBy', 'defaultColumn');
        $comments = User::find(1)->comments()->orderBy($column)->get();

        // use $comments in the template
    }
}

默认用户模型 + 简单控制器示例;获取评论列表时,只需根据 Input::get() 应用 orderBy()。 (一定要进行一些输入检查;))


有人已经在 Laravel 论坛上提出了这个建议,但我希望能够在 Controller 中执行此操作,以便我可以根据用户输入选择要排序的字段。也许我应该在问题中更清楚地说明这一点。
我添加了第二个示例
谢谢罗布,你让我走上了正轨。实际答案是 $comments = User::find(10)->comments()->orderBy('post_id')->get();它似乎需要 get() 方法才能工作。如果您可以将 get() 添加到您的答案中,我会将其标记为已接受的答案。
如果您要检索一条记录,这很有效,但如果您要检索多条记录,您将需要更多类似于 stackoverflow.com/a/26130907/1494454 的内容
如果您想订购 DESC 或 ASC 怎么办?
a
agm1984

我相信你也可以这样做:

$sortDirection = 'desc';

$user->with(['comments' => function ($query) use ($sortDirection) {
    $query->orderBy('column', $sortDirection);
}]);

这允许您在每个相关的评论记录上运行任意逻辑。你可以在里面放一些东西,比如:

$query->where('timestamp', '<', $someTime)->orderBy('timestamp', $sortDirection);

没有。我试过这个,它不起作用。这是我的情况:我有两个表(appointmentsschedules),查询很简单:按 schedules.datetime 降序获取 appointments order。我的解决方案是在表 appointments 中添加新列以存储表 schedules 中的 datetime。现在我只需按 appointments 订购。datetime我知道这不是最好的方法,但它可以解决问题。 XD
Y
Yunnosch

使用 sortBy... 可能会有所帮助。

$users = User::all()->with('rated')->get()->sortByDesc('rated.rating');


请注意,这会对集合进行排序,而不是在查询中。您获得了相同的结果,但排序是在 PHP 而不是 SQL 中完成的,这可能会影响性能。
M
MrSingh

试试这个解决方案。

$mainModelData = mainModel::where('column', $value)
    ->join('relationModal', 'main_table_name.relation_table_column', '=', 'relation_table.id')
    ->orderBy('relation_table.title', 'ASC')
    ->with(['relationModal' => function ($q) {
        $q->where('column', 'value');
    }])->get();

例子:

$user = User::where('city', 'kullu')
    ->join('salaries', 'users.id', '=', 'salaries.user_id')
    ->orderBy('salaries.amount', 'ASC')
    ->with(['salaries' => function ($q) {
        $q->where('amount', '>', '500000');
    }])->get();

您可以根据您的数据库结构更改 join() 中的列名。


S
Sebastiaan

我在关系字段上做了一个特征来排序。我对具有状态关系的网店订单有这个问题,并且状态有一个名称字段。

Example of the situation

使用 eloquent 模型的“连接”进行排序是不可能的,因为它们不是连接。它们是在第一个查询完成后运行的查询。所以我所做的就是做一个小技巧来读取雄辩的关系数据(如表、连接键和其他位置,如果包括),并将其连接到主查询中。这仅适用于一对一的关系。

第一步是创建一个特征并在模型上使用它。在该特征中,您有 2 个功能。第一个:

/**
 * @param string $relation - The relation to create the query for
 * @param string|null $overwrite_table - In case if you want to overwrite the table (join as)
 * @return Builder
 */
public static function RelationToJoin(string $relation, $overwrite_table = false) {
    $instance = (new self());
    if(!method_exists($instance, $relation))
        throw new \Error('Method ' . $relation . ' does not exists on class ' . self::class);
    $relationData = $instance->{$relation}();
    if(gettype($relationData) !== 'object')
        throw new \Error('Method ' . $relation . ' is not a relation of class ' . self::class);
    if(!is_subclass_of(get_class($relationData), Relation::class))
        throw new \Error('Method ' . $relation . ' is not a relation of class ' . self::class);
    $related = $relationData->getRelated();
    $me = new self();
    $query = $relationData->getQuery()->getQuery();
    switch(get_class($relationData)) {
        case HasOne::class:
            $keys = [
                'foreign' => $relationData->getForeignKeyName(),
                'local' => $relationData->getLocalKeyName()
            ];
        break;
        case BelongsTo::class:
            $keys = [
                'foreign' => $relationData->getOwnerKeyName(),
                'local' => $relationData->getForeignKeyName()
            ];
        break;
        default:
            throw new \Error('Relation join only works with one to one relationships');
    }
    $checks = [];
    $other_table = ($overwrite_table ? $overwrite_table : $related->getTable());
    foreach($keys as $key) {
        array_push($checks, $key);
        array_push($checks, $related->getTable() . '.' . $key);
    }
    foreach($query->wheres as $key => $where)
        if(in_array($where['type'], ['Null', 'NotNull']) && in_array($where['column'], $checks))
            unset($query->wheres[$key]);
    $query = $query->whereRaw('`' . $other_table . '`.`' . $keys['foreign'] . '` = `' . $me->getTable() . '`.`' . $keys['local'] . '`');
    return (object) [
        'query' => $query,
        'table' => $related->getTable(),
        'wheres' => $query->wheres,
        'bindings' => $query->bindings
    ];
}

这是读取雄辩数据的“检测”功能。

第二个:

/**
 * @param Builder $builder
 * @param string $relation - The relation to join
 */
public function scopeJoinRelation(Builder $query, string $relation) {
    $join_query = self::RelationToJoin($relation, $relation);
    $query->join($join_query->table . ' AS ' . $relation, function(JoinClause $builder) use($join_query) {
        return $builder->mergeWheres($join_query->wheres, $join_query->bindings);
    });
    return $query;
}

这是向模型添加范围以在查询中使用的函数。现在只需在您的模型上使用该特征,您就可以像这样使用它:

Order::joinRelation('status')->select([
    'orders.*',
    'status.name AS status_name'
])->orderBy('status_name')->get();

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅