Laravel array pagination - laravel

I am working on the pagination of the results from the research page. The code has two pages.
index page that direct to the page with the search form.
the second page is the result page where the output should be displayed. I want the results to be displayed in pages. my code is:
in the search function the output this is the code
$final_list = $this->paginate($final_list,5);
return view('results',['list' => $final_list]);
The paginate function is:
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);
}
in the result page I display the data and add the {!! $list->links() !!} to get pages.
The code displays the output for the first page. The issue I am facing is when I click to the second or any other page it direct me to the index page where I have to fill in the search form again before displaying the result of that page.
I don't understand what is wrong in this code. Could you please help me. thank you

you need to append your search filter data to your main data array.
$detail_data->appends(['keyword' => $keyword]);
I share sample code of controller
$keyword = $request->keyword;
$deals = Deal::join('category','category.id','=','deals.deal_category_id')
->join('users','users.id','=','deals.user_id')
->select('deals.*', 'category.cat_name', 'users.name AS username', 'users.profile_photo_path')
->where('deal_isApproved', '=', 'Approved');
$deals->where(function($query) use ($keyword) {
$query->where('deal_title', 'like', '%'.$keyword.'%')
->orWhere('category.cat_name', 'like', '%'.$keyword.'%');
});
$detail_data = $deals->paginate(20);
$detail_data->appends(['keyword' => $keyword]);
I blade template file
{{ $detail_data->links() }}

Related

Laravel 5.4 LengthAwarePaginator

My brain suddenly crashed on this one. Anyone care to help me is highly appreciated.
This is LengthAwarepaginator in laravel 5.4
Here is the code.
$collection = [];
foreach ($maincategories->merchantCategory as $merchantCat) {
foreach ($merchantCat->merchantSubcategory as $merchantSub) {
foreach($merchantSub->products as $products){
$collection[] = $products;
}
}
}
$paginate = new LengthAwarePaginator($collection, count($collection), 10, 1, ['path'=>url('api/products')]);
dd($paginate);
It displays perfectly but the problem is the items is 100. That's all my items and I specify it correctly. I need to display only 10.
Base on LengthAwarePaginator constructor. Here is the reference.
public function __construct($items, $total, $perPage, $currentPage = null, array $options = [])
Here is the screen shot.
Where did I go wrong? TY
When manually creating a paginator, you have to slice the result set yourself. The first parameter to the paginator should be the desired page of results, not the entire result set.
From the pagination documentation:
When manually creating a paginator instance, you should manually "slice" the array of results you pass to the paginator. If you're unsure how to do this, check out the array_slice PHP function.
I would suggest using a Collection to help out with this a little:
// ...
$collection = collect($collection);
$page = 1;
$perPage = 10;
$paginate = new LengthAwarePaginator(
$collection->forPage($page, $perPage),
$collection->count(),
$perPage,
$page,
['path' => url('api/products')]
);
For the heavy select and to avoid any multiple select to calculate the total from the table we unable to use model paginate
use Illuminate\Pagination\LengthAwarePaginator;
in your controller function
if(!isset($input["total"])){ //initial request
$total = //Find the total only one time.
$request->request->add(['total' => $total]); //Add it in the request so that we can print it in blade
}else
$total = $input["total"]; //After initial request
$currentPage = LengthAwarePaginator::resolveCurrentPage(); //page variable from GET or POST
$perPage = 30; //Page Length
$offset = ($currentPage - 1) * $perPage; //find the offset to pass in query
$specificRecords = /*Collect specific page records in array
if mysql then Select * from table limit $perPage offset $offset
if ms sql then OFFSET {$offset} ROWS FETCH NEXT {$perPage} ROWS ONLY */
$records = new LengthAwarePaginator($specificRecords,$total,$perPage,Null,[ "path" => "/pagepath" ]);
in blade:
<center>{{$records->appends(Request::except([ 'page','_token' ]))->links()}}</center>
Check Page and total variable in page tags ensure you added page in except list :)

How to create a paginator?

I've checked out the rather thin docs, but still unsure how to do this.
I have a collection. I wish to manually create a paginator.
I think I have to do something like, in my controller:
new \Illuminate\Pagination\LengthAwarePaginator()
But, what params do I need and do I need to slice the collection? Also how do I then display the 'links' in my view?
Could someone post a simple example how to create a paginator?
Please note, I don't want to paginate eloquent, eg. User::paginate(10);
Take a look at the Illuminate\Eloquent\Builder::paginate method for an example on how to create one.
A simple example of doing one using an eloquent model to pull out the results etc:
$page = 1; // You could get this from the request using request()->page
$perPage = 15;
$total = Product::count();
$items = Product::take($perPage)->offset(($page - 1) * $perPage)->get();
$paginator = new LengthAwarePaginator(
$items, $total, $perPage, $page
);
The first parameter accepts the results to display on the page that you're on
the second is the total number of results (The total number of items you're paginating, not the total number of items you're displaying on that page)
the third is the number per page you want to display
the fourth is the page that you're on.
You can pass in extra options as a fifth parameter if you want to customise things as well.
The links you should just be able to generate using the ->render() or ->links() method on the paginator as you would if you used Model::paginate()
With an existing collection of items you could do this:
$page = 1;
$perPage = 15;
$total = $collection->count();
$items = $collection->slice(($page - 1) * $perPage, $perPage);
$paginator = new LengthAwarePaginator(
$items, $total, $perPage, $page
);
You can create a Paginator like this:
$page = request()->get('page'); // By default LengthAwarePaginator does this automatically.
$collection = collect(...array...);
$total = $collection->count();
$perPage = 10;
$paginatedCollection = new \Illuminate\Pagination\LengthAwarePaginator(
$collection,
$total,
$perPage,
$page
);
According to the source code for LengthAwarePaginator (constructor)
public function __construct($items, $total, $perPage, $currentPage = null, array $options = [])
{
foreach ($options as $key => $value) {
$this->{$key} = $value;
}
$this->total = $total;
$this->perPage = $perPage;
$this->lastPage = (int) ceil($total / $perPage);
$this->path = $this->path != '/' ? rtrim($this->path, '/') : $this->path;
$this->currentPage = $this->setCurrentPage($currentPage, $this->pageName);
$this->items = $items instanceof Collection ? $items : Collection::make($items);
}
See more about LengthAwarePaginator
To display links in the view:
$paginatedCollection->links();
Hope this helps!

Laravel where statement and pagination

I have an SQL search where I use Eloquent whereRaw, and than paginatate results.
Proplem: the results are paginated and if I navigate to the next page the results will be gone and it will just "SELECT All " bacause laravel's pagination sends only ?page= GET request.
code:
if (Input::has('city')) {
$query .= ' and city = '.Input::get('city');
}
if (Input::has('area')) {
$query .= ' and area = '.Input::get('area');
}
if (Input::has('sub_location')) {
$query .= ' and sub_location = '.Input::get('sub_location');
}
if (Input::has('rent')) {
$query .= ' and rent = '.Input::get('rent');
}
if (Input::has('price_min') && Input::has('price_max')) {
$query .= ' and price < '.Input::get('price_max').' and price >'.Input::get('price_min');
}
$listings = ListingDB::whereRaw($query)->paginate(5);
return View::make('page.index')->with('title','Home')->with('listings',$listings);
so when I navigate to the next page all the Input is gone because laravel generates pagination only with ?page= GET variable, how can I solve it?
thank you.
you can append you query string to the pagination link
{!! $listings->appends(Input::all())->render() !!}
"Appending To Pagination Links
You may add 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:
{!! $listings->appends(['sort' => 'value'])->links() !!}
So in your case you need to add to pagination links like this if you have city and rent search applied then
{!! $listings->appends(['city' => 'london', 'rent' => 5000])->links() !!}
This will sort out your problem.

How can I paginate an array of objects in Laravel?

I'm building an application using Laravel 4.2. I have a model for units and another for users and pivot table user_units. Every user in this application can select a unit and add it to his favorite list then he can publish this unit with his information as an ad.
I want to select all units published by all users
The user_units (pivot) table has the following columns:
id
user_id
unit_id
publish
adtype
addinfo
created_at
updated_at
With relations methods on models
public function users() {
return $this->belongsToMany('User', 'user_units')
->withPivot('id','publish', 'adtype', 'addinfo');
}
public function units() {
return $this->belongsToMany('Unit', 'user_units')
->withPivot('id','publish', 'adtype', 'addinfo');
}
My query to select all published units by all users
// Get all published units by users for sale.
$users = User::all();
$publishedSaleUnits = [];
foreach($users as $user){
$userUnits = $user->units()->orderBy('adtype', 'desc')->get();
if(count($userUnits)){
foreach($userUnits as $unit){
if($unit->pivot->publish == 1 && $unit->unit_purpose_id == 1){
if( $unit->pivot->adtype ){
//push all featured ads onto the beginning of array
array_unshift($publishedSaleUnits, $unit);
}else{
//push all normal ads onto the end of array
array_push($publishedSaleUnits, $unit);
}
}
}
}
}
Now I got the result but I can't use pagination with results because it's an array of objects.
So is there any better solution to get all published units by user with pagination?
according to this article
https://www.itsolutionstuff.com/post/how-to-create-pagination-from-array-in-laravelexample.html
you can paginate your array by creating a custom method and using LengthAwarePaginator
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Collection;
use Illuminate\Pagination\LengthAwarePaginator;
class PaginationController extends Controller
{
public function index()
{
$myArray = [
['id'=>1, 'title'=>'Laravel CRUD'],
['id'=>2, 'title'=>'Laravel Ajax CRUD'],
['id'=>3, 'title'=>'Laravel CORS Middleware'],
];
$data = $this->paginate($myArray);
return view('paginate', compact('data'));
}
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);
}
}
Your approach to query the data is extremely inefficient. Fetch your data in one query. Nested traversing is not only hard to read but also a performance killer.
To the pagination problem:
Laravel provides a Pagignator Factory. With it you will be able to build your own Paginator with your own data.
It's as easy as
$units = Paginator::make($unit, count($unit), 10);
if you're using the Facade. Otherwise Illuminate\Pagination\Factory is the class you are looking for.
You can try my code with your own array,
$page = isset($request->page) ? $request->page : 1; // Get the page=1 from the url
$perPage = $pagination_num; // Number of items per page
$offset = ($page * $perPage) - $perPage;
$entries = new LengthAwarePaginator(
array_slice($contact_list, $offset, $perPage, true),
count($contact_list), // Total items
$perPage, // Items per page
$page, // Current page
['path' => $request->url(), 'query' => $request->query()] // We
need this so we can keep all old query parameters from the url
);
I got a better solution to paginate array result and I found the answer here
Paginator::make function we need to pass only the required values instead of all values. Because paginator::make function simply displays the data send to it. To send the correct offset paginated data to the paginator::make, the following method should be followed
$perPage = 5;
$page = Input::get('page', 1);
if ($page > count($publishedSaleUnits) or $page < 1) { $page = 1; }
$offset = ($page * $perPage) - $perPage;
$perPageUnits = array_slice($publishedSaleUnits,$offset,$perPage);
$pagination = Paginator::make($perPageUnits, count($publishedSaleUnits), $perPage);
this code work for me on laravel 8
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Collection;
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);
}
according to this refrence https://www.itsolutionstuff.com/post/how-to-create-pagination-from-array-in-laravelexample.html

Codeigniter variable not found message in sub views

I have stacked with the situation , please anyone help me !
Controller ->
public function index() {
$data = array();
$data ['tittle'] = 'Membership Payment';
$data ['page'] = $this->load->view('membership_payment', $data, true);
$data ['breadcrumb'] = $this->load->view('breadcrumb', $data, true);
$data['result'] = $this->payment_model->membership_payment();
$data['db']='---------------';
$this->load->view('master', $data);
View->master page
<?php echo $db; ?>
Master pages working fine , but problem is i have subpages membership_payment , in this page the data array variable are not working ,
Display the variable not found , there is any trick to pass data array to master subpage
Thanks in Advance !
ROB
I'm assuming that you've used $result which is the returned data of membership_payment(); method in the membership_payment view file.
If so, just change the order of the following line and put that over the $data['page'], as follows:
// ...
$data['result'] = $this->payment_model->membership_payment();
$data ['page'] = $this->load->view('membership_payment', $data, true);
// ...

Resources