Laravel — OrderBy не работает над коллекцией отношений

#php #laravel #eloquent

#php #laravel #красноречивый

Вопрос:

Недавно я перенес веб-сайт Laravel на другой сервер с той же настройкой (немного разные версии php, mariadb и т. Д.) И столкнулся с интересной проблемой.

Я использую пакет Team-Tea-Time / laravel-forum (ранее riari / laravel-forum) для обеспечения функциональности доски объявлений. На форуме в каждой теме есть ссылка для перехода к самому новому сообщению, которое отлично работало до перемещения. После перемещения эти ссылки вместо этого ведут к самому старому / первому сообщению.

Функциональность является частью модели потоков, в частности, функции getLastPostAttribute() .

Пытаясь разобраться в этом, я понял, что OrderBy в отношении posts просто не оказывает никакого эффекта. Независимо от того, по какому атрибуту я сортирую (например, created_at, последовательность) и какое направление сортировки я запрашиваю, всегда возвращается один и тот же порядок отправки и одно и то же первое сообщение.

Пример потока с 1811 сообщениями с разными временными метками и порядковыми номерами:

Упорядочение по последовательности ASC работает правильно, первым сообщением является сообщение с порядковым номером smalles. Однако это также порядок по умолчанию для этих отношений (см. Модель).

 $t->posts()->orderBy('sequence', 'asc')->first();
RiariForumModelsPost {#3268
    id: 113544,
    thread_id: 3995,
    author_id: 191,
    sequence: 1,
    created_at: "2018-05-08 08:21:20",
    updated_at: "2018-05-08 10:51:41",
    deleted_at: null,
    vote_count: 0,
}
 

Теперь, когда я меняю порядок сортировки на desc, он должен возвращать сообщение с наибольшим порядковым номером. Но вместо этого я получаю тот же результат, что и выше.

 $t->posts()->orderBy('sequence', 'desc')->first();
RiariForumModelsPost {#3297
    id: 113544,
    thread_id: 3995,
    author_id: 191,
    sequence: 1,
    created_at: "2018-05-08 08:21:20",
    updated_at: "2018-05-08 10:51:41",
    deleted_at: null,
    vote_count: 0,
}
 

Это сообщение, которое должно быть возвращено при сортировке по последовательности desc:

 RiariForumModelsPost {#3332
    id: 196449,
    thread_id: 3995,
    author_id: 534,
    sequence: 1814,
    created_at: "2020-12-16 14:55:54",
    updated_at: "2020-12-16 14:55:54",
    deleted_at: null,
    vote_count: 0,
}
 

Кто-нибудь сталкивался с этим раньше? После перемещения все остальное работает нормально, я понятия не имею, что может вызвать такую конкретную ошибку.

Комментарии:

1. оба имеют sequence значение 1, поэтому порядка нет. Ссылка на id это, похоже, одна и та же запись

2. В этом и заключается проблема — оба раза возвращается одно и то же сообщение, поэтому последовательность одинакова. Но есть 1810 других записей с разными номерами squence. Таким образом, вызов с сортировкой по последовательности DESC должен был вернуть вызов с последовательностью 1811.

3. Не могли бы вы отредактировать свой вопрос и добавить сообщение, которое должно быть правильным результатом?

4. Является ли последовательность столбцом в posts таблице или средством доступа? Можете ли вы опубликовать Thread модель? (в частности posts() , определение отношений), Post миграция модели и posts таблицы?

5. Кроме того, можете ли вы подтвердить выполняемый запрос $t->posts()->orderBy('sequence', 'desc')->toSql() ? Получаете ли вы желаемый результат, если выполняете запрос непосредственно в базе данных?

Ответ №1:

Когда вы смотрите на определение отношений в исходном коде Thread.php , вы видите, что posts они уже заказаны created_at по умолчанию:

 public function posts()
{
        $withTrashed = config('forum.preferences.display_trashed_posts') || Gate::allows('viewTrashedPosts');
        $query = $this->hasMany(Post::class)->orderBy('created_at');
        return $withTrashed ? $query->withTrashed() : $query;
}
 

Я думаю, вам нужно будет переопределить posts метод, удалить orderBy('created_at') инструкцию, и тогда ваш собственный OrderBy будет работать.

Комментарии:

1. Да, это выглядит многообещающе, только что увидел это благодаря функции -> toSql(), упомянутой выше. Как ни странно, тот же код отлично работал на старом сервере. Сейчас я попробую это сделать.

2. Да, перезапись этой функции устранила проблему для меня. Все еще странно, что этот пакет раньше работал нормально.. Я сообщу владельцу пакета, если кто-нибудь еще столкнется с этим. Спасибо!

3. Добро пожаловать! Глядя на историю , порядок по умолчанию, похоже, добавлен в феврале.