Laravel: как отсортировать по родственной модели с нумерацией страниц и фильтром - PullRequest
3 голосов
/ 19 января 2020

Уже три дня я блокирую свою конфигурацию. Я не могу отсортировать по модели, о которой сообщалось, я пробовал много методов, но ничего неубедительного, например, sortBy / sortByDes c, таблица соединений, но нет решения

Я хочу выполнить подкачку, сортировку и серверные фильтры , Фильтров может быть несколько. Все работает, кроме сортировки по связанной модели. Я получаю URL: http://127.0.0.1:8000/api/user/list?page=1&limit=30&sort=user__created_at&direction=desc&search__user__name=James&search__group__name=Client

запрос search__model__col позволяет мне объединить несколько запросов по нескольким моделям или столбцам

Вот мой код:

    public static function pagination(Request $request, $model, $relation, $modelStringify)
    {
        $modelSortBy = explode('__', $request->query('sort'))[0]; // user
        $tableSortBy = explode('__', $request->query('sort'))[1]; // created_at
        $query       = $request->query(); // ['page' => 1, 'limit' => 30...]
        $direction   = $request->query('direction'); // desc
        try {

            $model = $model->with($relation);

            //TODO : orderBy relationship
            if ($modelSortBy === $modelStringify): // modelStringify = 'user'
                $model->orderBy($tableSortBy, $direction);
            else:
                 // sort server side here 
            endif;

            foreach (array_keys($query) as $q) {
                if (strpos($q, 'search__') === 0) {
                    $modelSearchBy = explode('__', $q)[1]; // ['user', 'group']
                    $tableSearchBy = explode('__', $q)[2]; // ['name', 'name']
                    $valueSearchBy = $query[$q];
                    if ($modelSearchBy === $modelStringify):
                        $model->where($tableSearchBy, 'like', $valueSearchBy . '%');
                    else:
                        $model->whereHas($modelSearchBy, function (Builder $q) use ($valueSearchBy, $tableSearchBy) {
                            $q->where($tableSearchBy, 'like', $valueSearchBy . '%'); // $valueSearchBy = ['James', 'Client']
                        });
                    endif;
                }
            }
            return $model;
        } catch (Exception $e) {
            return response()->json(['message' => $e], 400);
        }
    }

Вот пример для user belongsTo group:

return response()->json([
    'items' => Utils::pagination($request, new User(), [
        'group',
    ], 'user')->paginate($limit)->toArray()
]);

Как я могу ввести сортировку по связанной модели в этой конфигурации?

Например, при сортировке по имени группы я получаю URL &sort=group__name

Спасибо

1 Ответ

1 голос
/ 24 января 2020

Не похоже, что это легко сделать в Laravel. Кто-то предложил синтаксис сделать это в Laravel здесь , но Тейлор закрыл вопрос.

На всех других ресурсах я мог найти людей предложить использование объединений , но это не совсем подходит для вашего более обобщенного подхода c.

Laravel также недавно представил "улучшения подзапроса", которые включают сортировку по подзапросу значение (ищите «Расширения Eloquent Subquery» на на этой странице ), но я не мог понять, как его использовать, чтобы упростить упорядочение по значению отношения Eloquent.

Я думаю, что ваш Лучше всего было бы использовать сторонний пакет, такой как тот, который связан с выпуском Github, fico7489 / laravel -eloquent-join . После его установки вы можете просто создать новый класс базовой модели, который использует черту use Fico7489\Laravel\EloquentJoin\Traits\EloquentJoin;, а затем наследовать этот класс от ваших моделей.

use Fico7489\Laravel\EloquentJoin\Traits\EloquentJoin;
use Illuminate\Database\Eloquent\Model;

abstract class BaseModel extends Model
{
    use EloquentJoin;
class ExampleModel extends BaseModel

Тогда вы сможете сортировать по соотношению, используя функцию orderByJoin:

$model->orderByJoin('<relationship>.<column>', $direction);

Приведенное выше значение relationship будет именем отношения, которое вы определили в модели.

Имейте в виду, что функция orderByJoin поддерживает только отношения BelongsTo и HasOne.

Что-то еще для имейте в виду, что ни Laravel, ни пакет laravel -eloquent-join не защищают вас от SQL внедрения в имена столбцов (или в значение направления в функции orderByJoin). Laravel docs рекомендует использовать белый список для имен столбцов:

PDO не поддерживает имена столбцов привязки. Поэтому вы никогда не должны позволять пользовательскому вводу указывать имена столбцов, на которые ссылаются ваши запросы, включая столбцы «упорядочить по» и т. Д. c. Если необходимо разрешить пользователю выбирать определенные столбцы для запроса, всегда проверяйте имена столбцов по белому списку разрешенных столбцов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...