Having problems getting my pagination to work in Laravel 5.2 I use a foreach to generate a list of objects where each object has a certain ranking. (competition)
The first query I used was this one:
$goedeDoelen = GoedDoel::orderBy('punten', 'desc')->simplePaginate(5);
This worked pretty ok, only problem was that my ranking would reset everything I would go to a different page.
Example: Page 1 has objects from rank 1 - 5, page 2 should have ranks 6-10. By using the first Paginate method, the second page would have objects starting from 1 again.
I have tried to work around this by adding the ranking as an extra attribute to my Eloquent collections.
$ranking = GoedDoel::orderBy('punten', 'desc')->get();
foreach($ranking as $key => $item) {
$item->ranking = $key+1;
}
After that I tried to use ->simplePaginate() on my updated collection. This gave an error.
I have created a custom Paginator.
$goedeDoelen = new Paginator($ranking, 5);
This isn't working as intended. When I go to my second page, the URL messes up and goes to another view.
How can I make sure the Paginator knows what my current URL is to which it has to apply the ?page=2
You need to use the paginate() method.
$goedeDoelen = GoedDoel::orderBy('punten', 'desc')->paginate(5);
{!! $goedeDoelen->links() !!}
The following Code illustrates manual pagination in Laravel
Sample Controller
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator as Paginator;
use App\Models\UserRechargeDetails;
class PaginateController extends Controller
{
//
public function index(Request $request)
{
$user_1 = new UserRechargeDetails;
// Get records from Database
$items = $user_1->all();
// Store records in an array
$records = [];
$i = 0;
foreach($items as $item)
{
$records[$i][0] = $item->user_name;
$records[$i][1] = $item->rech_mobile;
$i++;
}
// Current page for pagination
$page = $request->page;
// Manually slice array of product to display on page
$perPage = 2;
$offset = ($page-1) * $perPage;
$data = array_slice($records, $offset, $perPage);
// Your pagination
$final_data = new Paginator($data, count($records), $perPage, $page, ['path' => $request->url(),'query' => $request->query(),]);
/*
For Display links, you may add it in view page
{{ $data->links('pagination::bootstrap-4') }}
*/
return view('admin.pagination_new', ['data' => $final_data, 'j' => 1]);
}
}
Related
I have a fairly simple query which I load and add an element to the object and then sort it based on that custom element. I'd like to take 20 records or paginate it but when I do so, alot of data vanishes.
This is my code. The piece below gets all the records.
$fighters = Fighter::all();
The below code gets the points which is in a function and adds it to the fighter, fighterPoints does not initially exist in the collection, it is created and populated below.
foreach ($fighters as $fighter) {
$fighter->fighterPoints = $fighter->getFighterPoints($fighter->id);
}
Then i'd like to sort everything by those fighterPoints with the below function.
$sorted = $fighters ->sortByDesc(function ($item, $key) {
return $item->fighterPoints ;
});
When i do this i get all the records which are around 9000, it then sorts on the fighterPoints correctly:
The first record being something like [FighterName, 21309]
When i do $fighters = Fighter::paginate(20); it simply starts with [FighterName384, 200] which should be [FighterName, 21309] and just 20 results. The same thing happens with ::take(20) method.
What am I doing wrong here? I am laravel 8.
You want to paginate your $sorted variable right?!
To do that you have to
use Illuminate\Pagination\Paginator; // add
use Illuminate\Support\Collection; // add
use Illuminate\Pagination\LengthAwarePaginator; //add
...(your code)
// add
public function paginate($items, $perPage = 5, $page = null, $options = [])
{
$page = $page ?: (Paginator::resolveCurrentPage() ?: 1);
$items = $items instanceof Collection ? $items : Collection::make($items);
return new LengthAwarePaginator($items->forPage($page, $perPage), $items->count(), $perPage, $page, $options);
}
then, use that $sorted this way:
$fighters = $this->paginate($sorted);
reference:https://www.itsolutionstuff.com/post/laravel-6-paginate-with-collection-or-arrayexample.html
—————- EDIT ————
Sorry I misunderstood your question!
If you want to order eloquent, here is how you do it
$fighters = Fighter::orderBy('fighterPoints', 'desc')->paginate(20);
I hope that’s what you are looking for!
I am trying to create infinite scroll in laravel for that I am using default pagination and it is working fine but I want a pagination to use filtering.
public function infinite_scroll(Request $request)
{
$key = $request->input('key');
$group_name = $request->input('groupname');
$wachat = Wechat::where('key', '=', $key)->where('groupName', '=', $group_name)->orderBy('id', 'DESC')->paginate(2);
$this->response['values'] = $wachat;
$this->response['key'] = $key;
return response()->json(
$this->response
);
}
I am using this code and it is giving me this url in next url:
next_page_url: "http://localhost:8888/kc/kyo-webservice/public/api/v1/wechatinfinite?page=2"
But I want a filtering based on key and groupname for example when I pass a param groupname and key it should give me values.
When I am trying to get next page url it is not working I want my result for pagination based on my filter it should give me next page url like this:
next_page_url: "http://localhost:8888/kc/kyo-webservice/public/api/v1/wechatinfinite??key=smg1np1f77&groupname=group&page=2"
And it should give me result based on my filters.
used appends() pagination method here
Appending To Pagination Links
You may append to the query string of pagination links using the
appends method. For example, to append sort=votes to each pagination
link, you should make the following call to appends:
$wachat->appends(['key'=> $key,'groupname' => $group_name]);
in your controller do like that
public function infinite_scroll(Request $request)
{
$key = $request->input('key');
$group_name = $request->input('groupname');
$wachat = Wechat::where('key', '=', $key)->where('groupName', '=', $group_name)->orderBy('id', 'DESC')->paginate(2);
$wachat->appends(['key'=> $key,'groupname' => $group_name]);
$this->response['values'] = $wachat;
$this->response['key'] = $key;
return response()->json(
$this->response
);
}
I am on Laravel Framework version 5.1.45 (LTS).
One club can have many events. I am trying to list all the events, group them by year and show one page per year.
According to my Laravel version documentation "Currently, pagination operations that use a groupBy statement cannot be executed efficiently by Laravel. If you need to use a groupBy with a paginated result set, it is recommended that you query the database and create a paginator manually."
Here is my attempt to create the paginator manually and it seems to do the job:
public function index()
{
$page = Paginator::resolveCurrentPage() - 1;
$perPage = 1;
$events = new Paginator(Event::orderBy('date', 'desc')->groupBy(DB::raw('YEAR(date)'))->skip(($page - 1) * $perPage)->take($perPage + 1)->get(), $perPage, $page);
$events->setPath(['events/events']);
return view('events.index', ['events' => $events]);
}
And here is how I try to display the links at the bottom of the page.
{!! $events->render() !!}
If I remove the render bit, the page is displayed, albeit with no links. I can even go to the next page (year 2016) adding manually ?page=2 at the end of the url in my browser.
But if I leave the render bit in the index page, I get ErrorException in AbstractPaginator.php line 130: Array to string conversion.
What am I doing wrong?
Hope this snippet can help
public function index(Request $request)
{
$posts = Post::all()
->paginate($request->get('per_page', 25));
$grouped_by_date = $posts->mapToGroups(function ($post) {
return [$post->published_date => $post];
});
$posts_by_date = $posts->setCollection($grouped_by_date);
return view('posts.index', compact('posts_by_date'));
}
Basically redefine the collection with the grouped collection.
I have set of Ids as an array. It is out put of a complex search logic. For example my array is :
array(2,5,1,8,9,12,83,32);
Each of these IDs are valid and represents posts. So what I do is I just loop them in a for each loop and collect all data to a final array. Example :
foreach($ArrayOfIds as $id)
{
$posts[] = Post::findOrFail($id);
}
then I send this $posts to my view. Is it possible to implement laravel pagination in this scenario.? Keep in mind that I can't play any more with $ArrayOfIds.
Yes it's possible, example using Illuminate\Pagination\LengthAwarePaginator
public function showPost()
{
$posts = [];
foreach($ArrayOfIds as $id) {
$posts[] = Post::findOrFail($id);
}
$perPage = 6;
$paginator = new LengthAwarePaginator($posts, count($posts), $perPage);
$items = $paginator->getCollection();
return $paginator->setCollection(
$items->forPage($paginator->currentPage(), $perPage)
);
}
At first, I instantiate LengthAwarePaginator class and feed it with the arguments needed, see here. And then, as I need to set which posts belongs to which page, I then use forPage method from Illuminate/Support/Collection.
Something like that.
Why the paginate method doesn't work on this example ?
$shopIds = Follower::whereUserId($user->id)->orderBy('created_at','desc')->get()->pluck('shop_id')->toArray();
$shops = Shop::whereIn('id',$shopIds)->with('deals')->with('deals.likes')->paginate($this->perPage)->sortBy(function($likes) {
return $likes->count();
});
dd($shops);
Thank's for help ;)
The paginate is just working fine but the sortBy method is creating the problem for you because when you use sortBy it returns a new collection.
So finally your $shops is an instance of Illuminate\Support\Collection not of Illuminate\Pagination\LengthAwarePaginator.
You can try it as:
$paginated_shops = Shop::whereIn('id',$shopIds)
->with('deals')
->with('deals.likes')
->paginate($this->perPage);
$shops = $paginated_shops->sortBy(function($likes) {
return $likes->count();
});
$shops = new LengthAwarePaginator($shops, $paginated_shops->total(), $paginated_shops->perPage());
Remember to add use statement at the top of the class as:
use Illuminate\Pagination\LengthAwarePaginator;
Thank you guys!
I fix it like that
$shopIds = Follower::whereUserId($user->id)->orderBy('created_at','desc')->get()->pluck('shop_id')->toArray();
$shopIds = Shop::whereIn('id',$shopIds)->with('deals')->with('deals.likes')->get()->sortBy(function($likes) {
return $likes->count();
})->pluck('id')->toArray();
$orderedIds = implode(',',$shopIds);
$shops = Shop::whereIn('id', $shopIds)->whereNotIn('user_id', [$user->id])->orderByRaw(\DB::raw("FIELD(id, ".$orderedIds." )"))->paginate($this->perPage);
dd($shops);
and now I have an instance of Illuminate\Pagination\LengthAwarePaginator
Thank's
Like #Amit mentionned, $shops is a collection, thus not a LengthAwarePaginator. You are going to have to build the paginator and slice it yourself... not too complicated...
For example, let's assume you are hitting your route, calling your controller... then returning results to a view... Now that route is going to get requested with the pagination info in the request, you job is to get the result $shops into an array, slice the array into the right result for the page and return that to your view... I have not run this code... so take this as an example... but it will look something like:
public function yourController{
// This will return a collection... we will convert it to array later
$shops = Shop::whereIn('id',$shopIds)->with('deals')->with('deals.likes')->paginate($this->perPage)->sortBy(function($likes) {
return $likes->count();
});
$shopsArray = $shops->toArray();
// Here we deal with the slicing... you need to slice the page you are
// at the paging info is in the request...
// this basically gets the request's page variable... or defaults to 1
$page = Paginator::resolveCurrentPage('page') ?: 1;
// Assume 15 items per page... so start index to slice our array
$startIndex = ($page - 1) * 15;
// Length aware paginator needs a total count of items... to paginate properly
$total = count($shopsArray);
// Eliminate the non relevant items by slicing the array to page content...
$results = array_slice($shopsArray, $startIndex, 15);
$result = new LengthAwarePaginator($results, $total, 15, $page, [
'path' => Paginator::resolveCurrentPath(),
'pageName' => 'page',
]);
return view('yourView', compact('result'));
}