Как отсортировать Laravels API-ресурс - PullRequest
0 голосов
/ 24 сентября 2019

Я получаю список автомобилей из API-интерфейса моего приложения, используя VueJS с Axios на веб-интерфейсе и Ресурсы API Laravels на серверной части.Я использую локальные динамические области на модели Vehicle, чтобы выполнить фильтрацию. Все это прекрасно работает.

Теперь я хочу отсортировать результат перед его отправкой клиенту.Сортировка результата перед его передачей в VehicleCollectionResource приводит к ошибке, что некоторые функции недоступны в моем VehicleResourceCollection (например, $this->total() или $this->count()).

Передача результата запроса в результат каккак показано ниже, ResourceCollection получает действительную коллекцию с разбивкой по страницам (которая не отсортирована).При попытке сортировать коллекцию в CollectionResource сортируется только небольшая часть (одна «страница») всей коллекции.

Я не могу выполнить сортировку непосредственно в базе данных, поскольку для некоторых параметров сортировки требуетсядополнительные вычисления или информация из других моделей.

Итак, как я могу запросить записи из моей базы данных, отсортировать их, а затем разбить их на страницы, чтобы другие потом?Должен ли я реализовать свою собственную логику разбиения на страницы?

Моя функция toArray в VehicleCollectionResource:

public function toArray($request)
{
    $sortParameters = $this->sortParameters;
    $collection = $this->collection->sortBy(function ($vehicle) use ($sortParameters) {
        return $this->getSortingAttribute($vehicle, $sortParameters);
    })->toArray();

    return [
        'data' => $collection,
        'links' => [
            'self' => 'link-value'
        ],
        'pagination' => [
            'total' => $this->total(),
            'count' => $this->count(),
            'per_page' => 5,
            'current_page' => $this->currentPage(),
            'total_pages' => $this->lastPage()
        ]
    ];
}

Мой ApiVehicleController (получение запроса):

public function filter(Request $request)
{
    $query = Vehicle::available();

    // chain scopes to the query
    if ($request->has('producer') && $request->get('producer') !== null) {
        $query = $query->producer([$request->get('producer')]);
    }

    // other scopes ...

    $sortParameters = [
        'sortAfter' => $request->get('sort') ?? 'priceAsc',
        'mileage' => Mileage::where('id', $request->get('mileage'))->first() ?? NULL,
        'months' => Month::where('id', $request->get('duration'))->first() ?? NULL,
        'location' => $request->get('location')
    ];

    // Pass result to the CollectionResource
    return new VehicleCollectionResource($query->paginate(5), $sortParameters);
}

Направляясь к сортировке

1 Ответ

2 голосов
/ 24 сентября 2019

Факт:

  • Вы не можете отсортировать его после нумерации страниц, потому что в этот момент у вас есть только одна страница данных, а не вся коллекция

  • Перед выполнением запроса нельзя использовать такие функции, как count() или total().

Как следствие, существует только 2 допустимых варианта:

  1. Вы используете orderBy(), и вы заказываете свою коллекцию в запросе SQL (даже используя DB::raw() для построения сложных условий).SQL очень эффективен, и с его помощью можно выполнить почти все, но построить правильный запрос может быть нетривиально.
  2. Если вы не можете использовать SQL orderBy, вы не можете использовать paginate() утилита.Вместо использования вы получаете всю коллекцию ($query->get()), сортируете ее, а затем разбиваете на страницы вручную.Полезный метод для коллекции будет forPage.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...