Я создаю поток, который содержит два типа объектов: BluePerson и RedPerson. Чтобы создать поток, я извлекаю все оба объекта, а затем объединим их в одну коллекцию. После этого мне нужно их разбивать на страницы, но, как представляется, для создания красноречивых моделей и запросов БД, а не для коллекций. Я много видел о создании paginator вручную, но документация, особенно в API, разрежена (я даже не могу найти аргументы, которые принимает класс Paginator).
Как я могу разбивать на страницы результаты слияния моих коллекций?
public function index() { $bluePerson = BluePerson::all(); $redPerson = RedPerson::all(); $people = $bluePerson->merge($redPerson)->sortByDesc('created_at'); return view('stream.index')->with('people', $people); }
однако paginate для красноречивых моделей и запросов БД, а не коллекций, кажется.
Ты прав. но есть функция paginator для коллекций. forPage
Collection forPage(int $page, int $perPage)
Отдых просто.
public function foo() { $collection = collect([1,2,3,4,5,6,7,8,9,0]); $items = $collection->forPage($_GET['page'], 5); //Filter the page var dd($items); }
Если вы хотите использовать LengthAwarePaginator, просто создайте экземпляр. Как упоминалось в комментариях к предыдущему ответу, вам нужно будет установить путь для этого. Вам также необходимо убедиться, что вы разрешите «currentPage» и установите элементы, которые будут возвращены, прежде чем создавать экземпляр paginator. Все это можно сделать до / после создания экземпляра. Таким образом, функция может выглядеть примерно так:
function paginateCollection($collection, $perPage, $pageName = 'page', $fragment = null) { $currentPage = \Illuminate\Pagination\LengthAwarePaginator::resolveCurrentPage($pageName); $currentPageItems = $collection->slice(($currentPage - 1) * $perPage, $perPage); parse_str(request()->getQueryString(), $query); unset($query[$pageName]); $paginator = new \Illuminate\Pagination\LengthAwarePaginator( $currentPageItems, $collection->count(), $perPage, $currentPage, [ 'pageName' => $pageName, 'path' => \Illuminate\Pagination\LengthAwarePaginator::resolveCurrentPath(), 'query' => $query, 'fragment' => $fragment ] ); return $paginator; }
сfunction paginateCollection($collection, $perPage, $pageName = 'page', $fragment = null) { $currentPage = \Illuminate\Pagination\LengthAwarePaginator::resolveCurrentPage($pageName); $currentPageItems = $collection->slice(($currentPage - 1) * $perPage, $perPage); parse_str(request()->getQueryString(), $query); unset($query[$pageName]); $paginator = new \Illuminate\Pagination\LengthAwarePaginator( $currentPageItems, $collection->count(), $perPage, $currentPage, [ 'pageName' => $pageName, 'path' => \Illuminate\Pagination\LengthAwarePaginator::resolveCurrentPath(), 'query' => $query, 'fragment' => $fragment ] ); return $paginator; }
Вы можете попробовать разбивать на страницы оба набора и объединять их. Вы можете найти дополнительную информацию о разбиении на страницы в документах и api . Вот пример ручного создания своего собственного paginator …
$perPage = 20; $blue = BluePerson::paginate($perPage / 2); $red = RedPerson::paginate($perPage - count($blue)); $people = PaginationMerger::merge($blue, $red);
Я включил класс PaginationMerger ниже.
use Illuminate\Pagination\LengthAwarePaginator; class PaginationMerger { /** * Merges two pagination instances * * @param Illuminate\Pagination\LengthAwarePaginator $collection1 * @param Illuminate\Pagination\LengthAwarePaginator $collection2 * @return Illuminate\Pagination\LengthAwarePaginator */ static public function merge(LengthAwarePaginator $collection1, LengthAwarePaginator $collection2) { $total = $collection1->total() + $collection2->total(); $perPage = $collection1->perPage() + $collection2->perPage(); $items = array_merge($collection1->items(), $collection2->items()); $paginator = new LengthAwarePaginator($items, $total, $perPage); return $paginator; } }
Попробуйте следующее.
$arr = $pets->toArray(); $paginator->make($arr, count($arr), $perPage);