i implement the Yii infinite scroll extension. its working fine. its scrolling 10 by 10 from the database dynamically at last 10 values are repeated one more time.
i simply printing text values only but at last row ie last 10 values are repeated once.
i added my code here :
site controller
$criteria = new CDbCriteria;
$total = Recipe::model()->count();
$pages = new CPagination($total);
$pages->pageSize = 10;
$pages->applyLimit($criteria);
$posts = Recipe::model()->findAll($criteria);
$this->render('index', array(
'posts' => $posts,
'pages' => $pages,
));
my index page here:
<div id="posts">
<?php foreach($posts as $rec): ?>
<?php $rec_id=$rec['recipe_id']; $name=$rec['name']; ?>
<?php echo $name=$rec['name']; ?>
then i added my extension below
Infinite scroll ( and yii-infinite scroll) stops querying the server when it it hits a 404 error. on the next page. Yii framework keeps returning the last results for page numbers greater than what the result has.
This is why you keep seeing duplicated rows at the end of the results.. to prevent this add this piece of code to your corresponding action in your controller.
if(isset($_GET['Model_page'])){
if($model->search()->pagination->pageCount < $_GET['Model_page']+1){
throw new CHttpException(404,'No More results');
}
}
Where Model_page is to be substituted with Post_page etc depending on your model name and $model->search() is your dataProvider, if you have some other dataProvider please use that directly after it has been declared.
Related
I have a table with hundreds of thousand registers. I´m doing a pagination page with search capabilities using Zend Framework 3 and Doctrine 2. My problem is that I would like to limit the total number of registers to 500 independent of the search parameters and the pagination.
On the Controller:
// This will return the result of DQL
$registros = $this->regService->getRegisters($searchParameters);
$adapter = new DoctrineAdapter(new ORMPaginator($registros, false));
$paginator = new Paginator($adapter);
$paginator->setDefaultItemCountPerPage(20);
$paginator->setCurrentPageNumber($page);
return new ViewModel([
'registros' => $paginator
]);
So, the problem is that if I do a search with parameters thar get 2 thousand registers, the pagination will return all these registers and what I want to do is limit in 500 register
Thanks and best regards
From the code I'm not quite sure where your problem is; the implementation of the getRegisters($param) is missing.
However, to implement pagination you're on the right path.
Try the following:
$page = $this->params()->fromQuery('page', 1);
$itemsPerPage = $this->params()->fromQuery('itemsPerPage', null);
// I'm assuming your `getRegisters($param)` function returns QueryBuilder object
/** #var QueryBuilder $qb */
$qb = $this->getEntityManager()->createQueryBuilder();
// This query gets everything from Entity "Entity"
$qb->select('shortEntityName')
->from(\Namespace\To\Entity::class, 'shortEntityName');
// Create a Paginator, pass the QueryBuilder as parameter
$paginator = new Paginator(new OrmAdapter(new OrmPaginator($qb)));
// Set the current page (should be received from URL GET request)
$paginator->setCurrentPageNumber($page);
// Set the max items per page, defaulting to max of 500
$paginator->setItemCountPerPage($itemsPerPage ?: 500);
return [
'paginator' => $paginator,
];
Next to this you should also have a 'pagination' partial template somewhere you use for the pagination navigation, to use in the view. This template should accommodate the way you add the different GET parameters, e.g. &page=2 for the second page or &itemsPerPage=100 to show 100 items on a page instead of 500.
Based on comment, slightly revised last functions on the $paginator.
// If using code above, you can discard getting "itemsPerPage" from URL, no longer required
// Set the current page (should be received from URL GET request)
$paginator->setCurrentPageNumber(($page <= 10) ? $page : 10); // max allowed = 10
// Set the max items per page, defaulting to max of 500
$paginator->setItemCountPerPage(50); // always 50 per page
If requesting for a page say page number 3 in paginated items of a table in cakephp,
which is having only 2 pages, how do we show the last page ie page number 2?
I found out the solution here:-
cakephp paginator helper shows error when delete the last record from the last page
public function index() {
try {
$paginatedData = $this->Paginator->paginate();
} catch (NotFoundException $e) {
//get current page
$page = $this->request->params['named']['page'];
if( $page > 1 ){
//redirect to previous page
$this->redirect( array( "page" => $page-1 ) );
}else{
$paginatedData = array(); //no data to paginate so use empty array()
//you will have to check for this in the view and no longer display the pagination links, since they will NOT be defined
}
}
}
I've been playing around with pagination using arrays in php.
I have an array of posts that I use to break the content of a page up into smaller chunks. It works and returns the content as I would like.
<?php
// let's paginate data from an array...
$posts = array(
// array of posts
"blog/posts/06-19-tues.php",
"blog/posts/06-16-sat.php",
"blog/posts/05-26-sat.php",
"blog/posts/05-23-wed.php",
"blog/posts/05-09-wed.php"
);
// how many records should be displayed on a page?
$records_per_page = 3;
// include the pagination class
require 'zebra/Zebra_Pagination.php';
// instantiate the pagination object
$pagination = new Zebra_Pagination();
// the number of total records is the number of records in the array
$pagination->records(count($posts));
// records per page
$pagination->records_per_page($records_per_page);
// here's the magick: we need to display *only* the records for the current page
$posts = array_slice(
$posts,
(($pagination->get_page() - 1) * $records_per_page),
$records_per_page
);
?>
<?php foreach ($posts as $index => $post):?>
<?php include $post; ?>
<?php endforeach?>
<?php
// render the pagination links
$pagination->render();
?>
My question is now how to link to the individual posts from elsewhere on the site. Since they will, ultimately move from page to page, linking directly to the static file won't work. At first, I had given each post a unique id and used that to link to the post but that won't work now since the link will change, dynamically.
I've looked at array_search() and it looks promising but I don't understand it's use enough to get it to produce a hyperlink.
I'm not sure I've phrased this question all that well. apologies if I don't make much sense.
If I understand you correctly, I think something like this will work:
if (isset($_REQUEST['page']) {
$found = array_search($_REQUEST['page'], $posts);
if ($found) {
$pagination->set_page(floor($found/$records_per_page)+1);
}
}
Then you can use a link like
$link = 'whatever';
I am trying to build in a "search" box on a results page in my cakephp app. The page uses the cakePHP pagination component to show and "page" results. This is perfect, but I am having difficulties to get the next part to work.
The desired outcome:
A cakephp form (post) with an input box and a couple of select boxes, including a date selector so that I can select between dates. The user should be able to populate these fields and submit
On submit, the user selection should change the cakePHP pagination conditions in the controller
In the view I want the pagination bar to keep record of the user selection, so that when I filter through different pages, it keeps the users search. I understand this can be achieved using $this->passedArgs, hence why I am using post and not get.
The code:
// Form:
<?php
echo $this->Form->create('search', array('class' => false));
echo $this->Form->input('searchFor');
echo $this->Form->input('dateFrom');
echo $this->Form->input('dateTo');
echo $this->Form->end();
?>
// Controller:
if($this->request->is("post")) {
$filters = $this->request->data["search"];
$this->passedArgs["searchFor"] = $filters["searchFor"];
$this->passedArgs["dateFrom"] = $filters["dateFrom"]." 00:00:00";
$this->passedArgs["dateTo"] = $filters["dateTo"]." 00:00:00";
// Assign search parameters:
if($this->passedArgs["searchFor"] != "") {
$conditions["Model.field LIKE"] = "%".$this->passedArgs["searchFor"]."%";
}
$conditions["Model.created >="] = $this->passedArgs["dateFrom"];
$conditions["Model.created <="] = $this->passedArgs["dateTo"];
} else {
$conditions = array("Result.status_id >=" => 12);
}
$this->paginate = array(
'conditions' => $conditions,
'order' => array('Result.created ASC'),
'limit' => 20
);
$this->set("results",$this->paginate("Model");
// The view file:
<?php
$this->Paginator->options(array('url' => $this->passedArgs));
?>
Where I am now:
The initial page loads with all of the results
When I populate the search boxes it does return my results
The problem:
I am convinced the way I am doing it is incorrect as I now need to do 2 checks, a) being if results has been posted and b) check if there is passedArgs available. I am 100% convinced this is not the right way of doing it.
Let's say I have 2 free form fields for search, say name and surname, if I leave surname blank my url would be written as below, and this does not look or appear to be correct. That means I have to assign default values to ensure the items below does not happen, which does not appear to be very dynamic.
http://localhost/site/controller/action/surname:0/name:John/date:0/
On refresh it says the page does not exist because the posted values is not available anylonger.
usually I proceed like this in the controller:
//transform POST into GET
if($this->request->is("post")) {
$url = array('action'=>'index');
$filters = array();
if(isset($this->data['searchFor']) && $this->data['searchFor']){
//maybe clean up user input here??? or urlencode??
$filters['searchFor'] = $this->data['searchFor'];
}
//redirect user to the index page including the selected filters
$this->redirect(array_merge($url,$filters));
}
$conditions = array();
//check filters on passedArgs
if(isset($this->passedArgs["searchFor"])){
$conditions["Model.field LIKE"] = "%".$this->passedArgs["searchFor"]."%";
}
//paginate as normal
$this->paginate = array(
'conditions' => $conditions,
'order' => array('Result.created ASC'),
'limit' => 20
);
The idea is to transform the POST sent by your form into GET. so you wont have problems with the paginator nor the refresh
Hope this helps
What you want can be done a lot more simple and DRY by using this search plugin.
It automates what you want more or less plus it already can do more than your code.
So I suggest you to use the plugin directly or take a look at it how it does the trick. :)
public function index($page = 0) {
$this->load->library('pagination');
$conf = array(
'total_rows' => 11,
'base_url' => 'localhost/admin/product/index',
'per_page' => 10,
'use_page_numbers' => false
);
$this->pagination->initialize($conf);
$this->load->view('product/index');
}
In view
<?php echo $this->pagination->create_links(); ?>
In the first page it work correctly. When I click on the page 2 link, it only display ONE product, this was correct, but the pagination links for current page still in page ONE. Suppose this should be page TWO.
which part I did wrong?
Well, the pagination class uses "per_page" in the query string. So, you have to divide that number by 10 (in your case) and add 1 to get the real page number, i.e.:
localhost/product/index (page 1)
localhost/product/index?per_page=10 (page 2)
localhost/product/index?per_page=20 (page 3)
...
localhost/product/index?per_page={10n) (page n+1)
This is useful to use directly in the database limit clause:
$this->db->limit(10, $this->input->get('per_page'))...
I think that's why CI chose to do it that way....