Anyone know why $data->links() isn't working? Here's the error in view:
Whoops, looks like something went wrong.
1/1 FatalErrorException in pownerlist.php line 100: Call to undefined method Illuminate\Pagination\Paginator::links()
in pownerlist.php line 100
at HandleExceptions->handleShutdown()
But the paging is working just no links.
Hello,
In L5 there is no more method "links", only a method "render" for simple pagination. If you want a pagination as L4 you must create an object LengthAwarePaginator. As an example I use a service for my project :
<?php namespace App\Services;
use Illuminate\Pagination\Paginator;
use Illuminate\Pagination\LengthAwarePaginator;
abstract class Pagination
{
/**
* Create paginator
*
* @param Illuminate\Support\Collection $collection
* @param int $total
* @param int $perPage
* @return string
*/
public static function makeLengthAware($collection, $total, $perPage)
{
$paginator = new LengthAwarePaginator(
$collection,
$total,
$perPage,
Paginator::resolveCurrentPage(),
['path' => Paginator::resolveCurrentPath()]);
return str_replace('/?', '?', $paginator->render());
}
}
I get links with this function. I have to delete the trailing slash to get all working.
Maybe pagination in L5 will change but for now this is working fine.
How fo I use render? And can I append to querystring? And where does the above file you showed go, and how to use it?
In your controller :
$links = Pagination::makeLengthAware(Here your pagined collection, Here the total of records, Here the number of records per page);
And you send $links in your view.
To append you must change the function to integrate it. I didn't try it.
What is collection? And could you show how all this would look in my code above? And still confused on appending to query string. Where does the function go? Basically I want to use L5 not program it. A usage example of paging with a like clause as above, with render example.
Hello, I completed my function to have the append :
public static function makeLengthAware($collection, $total, $perPage, $appends = null)
{
$paginator = new LengthAwarePaginator(
$collection,
$total,
$perPage,
Paginator::resolveCurrentPage(),
['path' => Paginator::resolveCurrentPath()]
);
if($appends) $paginator->appends($appends);
return str_replace('/?', '?', $paginator->render());
}
A collection is what you get with a query like User::.....()->paginate(10);
You also need a query to get all the records for the second parameter like User::.....()->count();
L5 is still in progress so you cant expect to get all informations and documentation.
Here's another pager I've used, works great, I put it in the controller folder and include it:
<?php namespace App\Http\Controllers;
/*
* PHP Pagination Class
*
* @author David Carr - [email protected] - http://www.daveismyname.com
* @version 1.0
* @date October 20, 2012
*/
class Paginator{
/**
* set the number of items per page.
*
* @var numeric
*/
private $_perPage;
/**
* set get parameter for fetching the page number
*
* @var string
*/
private $_instance;
/**
* sets the page number.
*
* @var numeric
*/
private $_page;
/**
* set the limit for the data source
*
* @var string
*/
private $_limit;
/**
* set the total number of records/items.
*
* @var numeric
*/
private $_totalRows = 0;
/**
* __construct
*
* pass values when class is istantiated
*
* @param numeric $_perPage sets the number of iteems per page
* @param numeric $_instance sets the instance for the GET parameter
*/
public function __construct($perPage,$instance){
$this->_instance = $instance;
$this->_perPage = $perPage;
$this->set_instance();
}
/**
* get_start
*
* creates the starting point for limiting the dataset
* @return numeric
*/
private function get_start(){
return ($this->_page * $this->_perPage) - $this->_perPage;
}
/**
* set_instance
*
* sets the instance parameter, if numeric value is 0 then set to 1
*
* @var numeric
*/
//get_instance() added my me//////////////////////////////
public function get_instance()
{
return $this->_page;
}
private function set_instance(){
$this->_page = (int) (!isset($_GET[$this->_instance]) ? 1 : $_GET[$this->_instance]);
$this->_page = ($this->_page == 0 ? 1 : $this->_page);
}
/**
* set_total
*
* collect a numberic value and assigns it to the totalRows
*
* @var numeric
*/
public function set_total($_totalRows){
$this->_totalRows = $_totalRows;
}
/**
* get_limit
*
* returns the limit for the data source, calling the get_start method and passing in the number of items perp page
*
* @return string
*/
public function get_limit(){
return "LIMIT ".$this->get_start().",$this->_perPage";
}
//modified for eloquent dbal=====================================================================
public function get_limit2(){
//return "LIMIT ".$this->get_start().",$this->_perPage";
return $this->get_start();
}
public function get_perpage(){
//return "LIMIT ".$this->get_start().",$this->_perPage";
return $this->_perPage;
}
//modified for eloquent dbal=====================================================================
/**
* page_links
*
* create the html links for navigating through the dataset
*
* @var sting $path optionally set the path for the link
* @var sting $ext optionally pass in extra parameters to the GET
* @return string returns the html menu
*/
public function page_links($path='?',$ext=null)
{
$adjacents = "2";
$prev = $this->_page - 1;
$next = $this->_page + 1;
$lastpage = ceil($this->_totalRows/$this->_perPage);
$lpm1 = $lastpage - 1;
$pagination = "";
if($lastpage > 1)
{
$pagination .= "<div class='pagination pagination-centered'><ul>";
if ($this->_page > 1) {
$pagination.= "<li><a href='" . $path . "$this->_instance=$prev" . "$ext'>Previous</a></li>";
} else {
$pagination.= "<li><span class='disabled'>Previous</span></li>";
}
if ($lastpage < 7 + ($adjacents * 2))
{
for ($counter = 1; $counter <= $lastpage; $counter++)
{
if ($counter == $this->_page) {
$pagination.= "<li><span class='current'>$counter</span></li>";
} else {
$pagination.= "<li><a href='" . $path . "$this->_instance=$counter" . "$ext'>$counter</a></li>";
}
}
}
elseif($lastpage > 5 + ($adjacents * 2))
{
if($this->_page < 1 + ($adjacents * 2))
{
for ($counter = 1; $counter < 4 + ($adjacents * 2); $counter++)
{
if ($counter == $this->_page) {
$pagination.= "<li><span class='current'>$counter</span></li>";
} else {
$pagination.= "<li><a href='" . $path . "$this->_instance=$counter" . "$ext'>$counter</a></li>";
}
}
$pagination.= "...";
$pagination.= "<li><a href='".$path."$this->_instance=$lpm1"."$ext'>$lpm1</a></li>";
$pagination.= "<li><a href='".$path."$this->_instance=$lastpage"."$ext'>$lastpage</a></li>";
}
elseif($lastpage - ($adjacents * 2) > $this->_page && $this->_page > ($adjacents * 2))
{
$pagination.= "<li><a href='".$path."$this->_instance=1"."$ext'>1</a></li>";
$pagination.= "<li><a href='".$path."$this->_instance=2"."$ext'>2</a></li>";
$pagination.= "...";
for ($counter = $this->_page - $adjacents; $counter <= $this->_page + $adjacents; $counter++)
{
if ($counter == $this->_page) {
$pagination.= "<li><span class='current'>$counter</span></li>";
} else {
$pagination.= "<li><a href='" . $path . "$this->_instance=$counter" . "$ext'>$counter</a></li>";
}
}
$pagination.= "..";
$pagination.= "<li><a href='".$path."$this->_instance=$lpm1"."$ext'>$lpm1</a></li>";
$pagination.= "<li><a href='".$path."$this->_instance=$lastpage"."$ext'>$lastpage</a></li>";
}
else
{
$pagination.= "<li><a href='".$path."$this->_instance=1"."$ext'>1</a></li>";
$pagination.= "<li><a href='".$path."$this->_instance=2"."$ext'>2</a></li>";
$pagination.= "..";
for ($counter = $lastpage - (2 + ($adjacents * 2)); $counter <= $lastpage; $counter++)
{
if ($counter == $this->_page) {
$pagination.= "<li><span class='current'>$counter</span></li>";
} else {
$pagination.= "<li><a href='" . $path . "$this->_instance=$counter" . "$ext'>$counter</a></li>";
}
}
}
}
if ($this->_page < $counter - 1) {
$pagination.= "<li><a href='" . $path . "$this->_instance=$next" . "$ext'>Next</a></li>";
} else {
$pagination.= "<li><span class='disabled'>Next</span></li>";
}
$pagination.= "</ul></div>\n";
}
return $pagination;
}
}
Controller code:
public function petlist()
{
include 'paginator.php';
if(isset($_REQUEST['t1']))
{
$t1 = $_REQUEST['t1'];
}
else
{
$t1 = "";
}
$petsearch = $t1;
$petsearch = $petsearch . "%";
$krows = \Illuminate\Support\Facades\DB::table('pets')->where('petname', 'like', $petsearch)->count();
$pages = new Paginator('5','p');
$pages->set_total($krows);
$data['pets'] = \Illuminate\Support\Facades\DB::table('pets')
->where('petname', 'like', $petsearch)
->orderBy('petname', 'asc')
->skip($pages->get_limit2())->take($pages->get_perpage())->get();
$data['page_links'] = $pages->page_links('?','&t1='.$t1);
return \View('pet/petslist2')->with('data',$data['pets'])->with('data2',$data['page_links']);
}
view code at bottom you simply echo the page links::
echo $data2;
In fact heres the whole view:
<html>
<head>
<link rel="stylesheet" href="include/styleplist.css" type="text/css">
</head>
<body>
<div>
Pets
<form method="get" action="pets">
<label>sch</label><input type="text" name="t1" value=""> <input type="submit" name="submit" value="Search">
</form>
</div>
<?php
//echo "<body>";
echo "<br>";
echo "<div id=tbl-container>";
echo "<table>";
echo "<thead>";
echo "<tr>";
echo "<th>PET ID</th>";
echo "<th>PET NAME</th>";
echo "<th>SPECIES</th>";
echo "<th>SEX</th>";
echo "<th>OWNER ID</th>";
echo "<th>PET OWNER</th>";
echo "<th>STREET</th>";
echo "<th>date</th>";
echo "<th>ocheck</th>";
echo "<th>PIC</th>";
echo "<th>EDIT</th>";
echo "</tr>";
echo "</thead>";
echo "</table>";
echo "</div>";
//echo "<tbody>";
$picpath = "upload/";
echo "<div id=tbl-container2>";
echo "<table>";
foreach ($data as $row){
//var_dump($row->petname);
//$tmppetid = $pets_Row['petid'];
echo "<tr onMouseover=this.bgColor='lightgrey' onMouseout=this.bgColor='#FFFFFF'>";
echo "<td>".$row->petid."</td>";
echo "<td>".$row->petname."</td>";
//////////////////////////////
echo "<td>" . $row->species . "</td>";
echo "<td>" . $row->sex . "</td>";
echo "<td>" . $row->ownerid . "</td>";
echo "<td>" . $row->petowner . "</td>";
echo "<td>" . $row->ostreet . "</td>";
echo "<td>" . $row->odate . "</td>";
echo "<td>" . $row->ocheck . "</td>";
if (empty($row->dogpic)) {
echo "<td>" . " " . "</td>";
}
else {
//$picpath = "public/upload";
$linev = "";
$linev = "<td><a href=\"{$picpath}{$row->dogpic}\" target=\"_blank\">";
$linev = $linev . "<img width=\"80\" border=\"0\"";
$linev = $linev . "src=\"{$picpath}{$row->dogpic}\"></a></td>";
echo $linev;
//echo $linev;
}
//echo "<td>" . $row->dogpic . "</td>";
/////////////////////////////////
//echo "<td>".$pets_Row->petname."</td>";
echo "<td><a href=\"petedit?petid={$row->petid}\">Edit</a></td>";
echo "<tr>";
}
//echo public_path();
//echo "</tbody>";
echo "</table>";
echo "</div>";
echo "<br>";
echo $data2;
echo "<br>";
//echo "<a href='/laravel4/public/index.php/upload/chance.jpg'>here<img src='/laravel4/public/index.php/upload/chance.jpg'></a?";
echo "<a href='/laravel/public/owners'>owners</a>";
////added
$t1 = Session::get('petsearch');
//echo "the session is===".Session::get('t1');
$areturn = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
echo "<br>";
$haystack = $areturn;
$needle = '?';
$pos = strripos($haystack, $needle);
if ($pos === false) {
$areturn = $areturn."?p=1&t1=".$t1;
Session::put('areturn', $areturn);
} else {
Session::put('areturn', $areturn);
}
echo "jimmie here is a return: ".Session::get('areturn');
////added
?>
</body>
</html>
Of coure you can easily convert to blade in view: I have tested this pager with over 500,000 records, and it does paginate efficiently. I guess if I have to do all that stuff for pagination, I might as well use a known good pager. And various versions of this is used on several large sites.
Also, wouldn't the laravel 5 modified paginator require all the records in query first, then paginate them? Have you tested this on say 500,000 to a million records? Even a like clause could return thousands of records. An efficient pager will only pull the perpage amount at a time, in my case 5 records is all thats being queried at a time in main query. Of course the count will count all results, but this is for the math to figure out the pagination. If you happen to run a test please let me know how fast the next page comes up. But test with at least 100,000 records if you can.
You still didn't show how you call the modified pager, actual usage of it to get the results, you are only showing the modified function to make it work. Could you possibly show like I did a complete example of using it in controller (the query) and view with appending the querystring? With the use statements at top also. I'd really like to try it and test it.
Hello,
The paginator doesn't need to get all the records, just the count of all like yours.
To integrate my function to your code you can do something like that :
public function petlist()
{
if(isset($_REQUEST['t1']))
{
$t1 = $_REQUEST['t1'];
}
else
{
$t1 = "";
}
$petsearch = $t1;
$petsearch = $petsearch . "%";
$krows = \DB::table('pets')->where('petname', 'like', $petsearch)->count();
$data['pets'] = \DB::table('pets')
->where('petname', 'like', $petsearch)
->orderBy('petname', 'asc')
->skip($pages->get_limit2())->take($pages->get_perpage())->get();
$data['page_links'] = Pagination::makeLengthAware($data['pets'] , $krows, 5, ['t1' => $t1]);
return view('pet/petslist2')->with('data',$data['pets'])->with('data2',$data['page_links']);
}
With this use if you keep my namespace :
use App\Services\Pagination;
btw why do you use $_REQUEST when you have a nice class in Laravel ? There is also an helper for the views. Why dont you use the models ?
Offtopic, but looking at your view above jimgwhit, you should really consider using blade to make your views easier to edit and view :)
To get it working I had to add some stuff to calc offset:
if(isset($_REQUEST['page']))
{
$page = $_REQUEST['page'];
}
else
{
$page = "1";
}
$perpage = "5";
$offset = ($page - 1) * $perpage;
So I could have the variables for this line:
->skip($offset)->take($perpage)->get();
Here's the lastest, it is now working but an error is showing on view page:
owners
sch
ownerid oname
3 JEFFERY
15 jimbob2
16 jimbob3
32 jimbob33
33 jimbob34
«
1
2
3
4
5
6
7
8
9
10
11 THESE SHOW FINE IN BROWSER I COPIED AND PASTED VIEW PAGE RESULTS
»
Whoops, looks like something went wrong.
1/1 FatalErrorException in pownerlist.php line 102: Call to a member function render() on array
in pownerlist.php line 102
at HandleExceptions->handleShutdown()
Links are showing correct in browser... Line102 is where I have
<?php echo $data2; ?>
$data2 shows up, but with above error... Do I need a use statement at top of the view?.. Call to a member function render() on array???
And I plan on blade, one step at a time, have to work this out first.
YAH! Got it, in view I had a stray line of code
<?php echo $data->render(); ?>
that was above this line:
<?php echo $data2; ?>
So it works now. This is the line that works:
<?php echo $data2; ?>
Thanks for your help here. I plan on further testing with 500,000 records, will post results.
I tested with 500,000 records, works good. I tested mine from above, they both took about 4 seconds.. to go from page to page.
Here's a quick Stored Procedure for mysql where I add testing data Hope it helps someone:
DELIMITER $$
CREATE
PROCEDURE `pbackdate`.`sp_addto`()
BEGIN
DECLARE v1 INT;
DECLARE voname varchar(30);
DECLARE vostreet varchar(15);
SET v1 = 52;
WHILE v1 < 500000
DO
SET v1 = v1 + 1;
SET voname = CONCAT('jimbob',v1);
set vostreet = CONCAT('jstreet',v1);
insert into powners
(oname, ostreet)
values
(voname, vostreet);
END WHILE;
END$$
DELIMITER ;
To be fair I'm a bit dissapionted with this aspect of L5. Still think Taylor will revert to a pagination that's more user friendly. Seems a bit of work to do something that was so simple in L4, especially in CRUD apps.
Actually once bestmomo's class above is implemented the pagination is exactly the same you just have to figure the skip and take:
->skip($offset)->take($perpage)->get();
But that's easy. Only a few more lines of code. I agree I also like v4.2 where this wasn't necessary. But it was fun figuring this out. And the pager I showed above is another major pagination class. Uses the same style of links, easy to implement. I modified it for the skip and take, originally it combined them in a $LIMIT variable. It's used on many sites with slight variations. Google digg style pagination.
I know this post is pretty old, but I read it diligently while trying to solve this same problem. After about an hour of digging I realized that, at least in 5.1, there is an option to fix this problem. The following code is working in my current project:
$items = query->paginate($limit);
$items->setPath('search');
and it gives me urls like
/search?page=3&limit=20
Hope this helps someone.
Sign in to participate in this thread!
The Laravel portal for problem solving, knowledge sharing and community building.
The community