Codeigniter Pagination and MySQL Query with dynamic parameters - php

Let me explain my issue in detail
I have a table called products
Products : Name , views , sale_wanted , added_date
I am listing all my products in a view .
I am handling sale wanted through a flag means 0 or 1.
There are some links to sort the listing.
Most Viewed
Wanted
For Sale
New Arrivals
Now when user clicks all the listing is sorted according to the parameter i am sendig.
I want to use pagination class of Codeigniter.
Here comes some issues.
When i am clicking let suppose Wanted and sending a parameter it lists all the products wanted.
Now i click on a pagination link and the wanted parameter is gone
and the list becomes without wanted parameter.
Same goes with the other Anchors.
I have to restrict it so it still has my parameter.
The second problem is that what i see Codeigniter is laking.
I need some links that user can select. Means i want to give the user functionality to select how many products he wants to see in one page.
Let suppose 5 ,10 ,15 ,20
Choosing the greater number will reduce the number of pages.
And still i want the same functionality.
The important point is that i want to handle all this just in one shot means i dont want to duplicate my code for every anchor.
I need suggestions from expert and any help regarding Pagination library.

$seg=3
$noOfresultsToshow=$this->uri->segment('5')//use if else for by default no of results
$typeOfresult=$this->uri->segment('4'); //Most Viewed Wanted For Sale New Arrivals
$config['total_rows'] = $countqueryresults;// mention the total rows here
$config['per_page'] = $noOfresultsToshow;
$config['uri_segment'] = $seg;
$this->pagination->initialize($config);
$data['yourvariable'] = $this->model_name->getData($config['per_page'], $this->uri->segment($seg),$typeOfresult);
$data['links'] = $this->pagination->create_links();
in your view file echo $links;

I have found a solution for the issue.
I have made two methods in Codeigniter Pagination library
Here they are
Defined two new variables
var $base_link = '';
var $per_page_link = TRUE;
var $per_page_array = array();
The user can define both of them while initializing
$config['per_page_link'] = TRUE;
$config['per_page_array'] = array(5,10,15,20);
$this->pagination->initialize($config);
Now the methods
public function create_per_page()
{
$CI =& get_instance();
$output = '';
$current = $CI->uri->segment(3,5);
if($this->per_page_link === TRUE AND count($this->per_page_array) > 1){
foreach($this->per_page_array as $row){
if($current == $row){
$output .= $this->cur_tag_open . $row . $this->cur_tag_close;
$output .= ' ';
}else{
$output .= ''.$row.'';
$output .= ' ';
}
}
}
return $output;
}
And the other is create_per_page_links(). I have just copied the code of create_links method in it and modified it. In the start of create_per_page_links() i have added these extra lines.
$this->per_page = $CI->uri->segment(3,5);
$this->uri_segment = $CI->uri->segment(4,1);
However, This will only work with segments on. i haven't tested it with query string. Also if per_page_link is FALSE both methods will not work.
Calling create_per_page_links will generate the following
« First < 1 2 3 4 5 > Last »
And create_per_page will generate the following
5 10 15 20
And Done

Related

Get pagination results in Active Collab API

I have just discovered you can get pagination results through the api by passing in the page parameter like so:
$projects = $client->get('projects/147/time-records?page=3')->getJson();
Is there a way of knowing how many time records a project has so I know how many times I need to paginate?
Alternatively, how would I go about retrieving several pages worth of data - i'm struggling with the code!
I have created an issue on Github - will await a response.
For now, I do the following:
// Get all the projects
// Set the page number
$page = 1;
// Create an empty array
$project_records = array();
// Get the first page of results
$project_records_results = $client->get('projects?page=' . $page)->getJson();
// Merge the results with base array
$project_records = array_merge($project_records, $project_records_results);
// Get the next page of results,
// if it returns something merge with the base array and continue
while ($project_records_results = $client->get('projects?page=' . ++$page)->getJson()) {
$project_records = array_merge($project_records, $project_records_results);
}
Sure. All paginated results will include following headers:
X-Angie-PaginationCurrentPage - indicates current page
X-Angie-PaginationItemsPerPage - indicates number of items per page
X-Angie-PaginationTotalItems - indicates number of items in the entire data set.
When you get header values, simple:
$total_pages = ceil($total_items_header_value / $items_per_page_header_value);
will give you number of pages that are in the collection.
Alternative: You can iterate through pages (by starting with page GET parameter set to 1, and incrementing it) until you get an empty result (page with no records). Page that returns no records is the last page.
Please note, that the headers are now all lowercase (v1)!
So the answer above should be corrected.
To get them call:
$headers = $client->get($path)->getHeaders();
Working code example from /api/v1/:
$paginationCurrentPage = isset($headers['x-angie-paginationcurrentpage'][0]) ? $headers['x-angie-paginationcurrentpage'][0] : NULL;
$paginationItemsPerPage = isset($headers['x-angie-paginationitemsperpage'][0]) ? $headers['x-angie-paginationitemsperpage'][0] : NULL;
$paginationTotalItems = isset($headers['x-angie-paginationtotalitems'][0]) ? $headers['x-angie-paginationtotalitems'][0] : NULL;

divide xml into chunks based on url in php

I have a robots.txt file
in that i generate dynamic sitemap links.
I get the following links if i run the robots.txt file in the browser.
Here you get 5 sitemap links for each language.
Reason: there are 10 products in database.
i want to show only two products per link. so i divided the total no.of products with no.of products on one page.
Sitemap:http://demo.com/pub/sitemap_products.php?page=1&lang=it_IT
the part in bold is dynamic.
code in: sitemap_products.php
$Qproduct : returns an array of all the products in the db for all the languages.
So the bellow loop generates an xml having links of the products for the language in the sitemap url
for eg.
if the link is
Sitemap:http://demo.com/pub/sitemap_products.php?page=1&lang=it_IT
it will generate all the products present in IT language.
The xml links that are generated now are based on languages that we get from url.
but i want to divide them into chunks of 2 product's xml per sitemap link.
while($Qproduct->next())
{
if(!isset($page_language[$Qproduct->valueInt('language_id')]))
{
$page_language[$Qproduct->valueInt('language_id')] = mxp_get_page_language($MxpLanguage->getCode($Qproduct->valueInt('language_id')), 'products');
}
if($Qproduct->valueInt('language_id') == $QproductLang->valueInt('languages_id'))
{
$string_to_out .= '<url>
<loc>' . href_link($page_language[$Qproduct->valueInt('language_id')], $Qproduct->value('keyword'), 'NONSSL', false) . '</loc>
<changefreq>weekly</changefreq>
<priority>1</priority>
</url>';
}
}
what i wish to do is apply a condition so that it gives me exactly two products links in xml when page=1(see in the sitemap links) instead of all the 10 products link in xml.
similarly if page=2 it should display next 2 products. and so on.
I am a bit confused in the condition that i am supposed to apply.
Please help me out.
First of all, use an XML library to create the XML, not string concatenation. Example:
$loc = href_link($page_language[$Qproduct->valueInt('language_id')], $Qproduct->value('keyword'), 'NONSSL', false);
$url = new SimpleXMLElement('<url/>');
$url->loc = $loc;
$url->changefreq = 'weekly';
$url->priority = 1;
In your case, you can even easily wrap that into a function that just returns such an element and which has two parameters: $Qproduct and $page_language (as string, not array (!)).
But that's just some additional advice, because the main point you ask about is the looping and more specifically the filtering and navigating inside the loop to the elements you're interested in.
First of all you operate on all results by looping over them:
while ($Qproduct->next())
{
...
}
Then you say, that you're only interested in links of a specific language:
while ($Qproduct->next())
{
$condition = $Qproduct->valueInt('language_id') == $QproductLang->valueInt('languages_id');
if (!$condition) {
continue;
}
...
}
This already filters out all elements not interested in. What is left to keep track and decide which elements to take:
$page = 1;
$start = ($page - 1) * 2;
$end = $page * 2 - 1;
$count = 0;
while ($Qproduct->next())
{
$condition = $Qproduct->valueInt('language_id') == $QproductLang->valueInt('languages_id');
if (!$condition) {
continue;
}
$count++;
if ($count < $start) {
continue;
}
...
if ($count >= $end) {
break;
}
}
Alternatively, instead writing this all the time your own, create an Iterator for $Qproduct iteration and the use FilterIterator and LimitIterator for filtering and pagination.

Pagination current page incorrect when 'use_page_numbers'

I'm using CI Pagination library on my website and now with $config['use_page_numbers'] set to TRUE the current page is always the first. Everything works fine, except this.
Other settings:
$config['uri_segment'] = 2;
$config['prefix'] = "p";
$route['mypage/p(:num)'] = "citate/index/$1";
This is the function that calculate the current page (the output is correct). When I'm on first page returns 1, when on third page returns 3 and so on:
function getPagCurr($offset, $limit){
if( ! $offset) return $page = 1;
else return ($offset/$limit)+1;
}
... though, it's not working.
I've try to set up manually, just for testing, the value of $config['cur_page'] = 2 (so this means that the second link should be considered as active) but no change at all.
CI version is latest.
LE: SOLUTION
It seems that the prefix is the problem here. With my actual configuration the link will be like this www.site.com/mypage/p2, which is not working.
The working link would be www.site.com/mypage/p/2/ with the uri_segment = 3 and route mypage/p/(:num).
However, I really want to have the first link structure so here's my solution (not a good one because you have to modify some system library code):
Pagination.php (start line 166):
// Set current page to 1 if using page numbers instead of offset
if ($this->use_page_numbers AND $this->cur_page == 0)
{
$this->cur_page = $base_page;
}
..changed to:
// Set current page to 1 if using page numbers instead of offset
if ($this->use_page_numbers AND $this->cur_page == 0)
{
$current_page = $CI->uri->segment($this->uri_segment); //get pNUM
$current_page = substr($current_page, 1); //remove prefix
$this->cur_page = $current_page; //set current page
}
... and now it works!
If anybody have a better solution please tell!
Thanks.
Yes you are right it will not work because your segment got a p(p2)
To do this you must have to modify the core but i will say dont modify the core just extend the pagination class and modify the code with following:
Add a new class variable
var $use_rsegment = FALSE;
Then modify the create_links() around line 157
//add
$_uri_segment = 'segment';
if($this->use_rsegment){
$_uri_segment = 'rsegment';
}
//modify
if ($CI->uri->$_uri_segment($this->uri_segment) != $base_page)
{
$this->cur_page = $CI->uri->$_uri_segment($this->uri_segment);
// Prep the current page - no funny business!
$this->cur_page = (int) $this->cur_page;
}
The uri rsegment is the new routed segment, now set the pagination config like this
$config['use_rsegment'] = TRUE;
$this->pagination->initialize($config);
So you can use both option when ever you need. When you have route set rsegment true

CI class Pagination links trouble

This is the code i currently have.
P.S. I am currently editing this, trying to solve this problem whilst waiting for someone to solve it here. Im not quite sure why this is happening.
Pagination:
$character = $this->uri->segment(3);
$config['base_url'] = base_url() . 'index.php/Controller/function/'.$character;
$config['total_rows'] = $this->Model->browse_total_rows();
$config['per_page'] = 1;
$config['num_links'] = 10;
$config['uri_segment'] = 4;
$this->pagination->initialize($config);
if(!is_numeric($character)){$data['records'] = $this->Model->get_records_filtered($character,$config['per_page'],$this->uri->segment(4));}
else{ $data['records'] = $this->Model->get_records($config['per_page'], $this->uri->segment(3));}
$data['links'] = $this->pagination->create_links();
$this->load->view('browse', $data);
Whenever i go to my browse page, instead of being on the page 1 of my page on pagination. it is defaulted that im on page 2. Why? because i see this as my link.
1 2 3 >
Plus, i can't click on link 2 but i can on link 1. I don't know if this is how pagination_links works. but i find it odd. Anyways, im not sure if its related to my other problem.
The character part is for the letter chosen, so for example i only want to view results with A as their first letter the url should be.
index.php/controller/function/A/
So the per page of the pagination will be placed on the 4th segment. It has no error that way. But when i don't click on any letter and just show all results.
Whenever i click on a link(per page). The url looks like this.
index.php/controller/function/2/
but when i click on the next page, it goes as
index.php/controller/function/2/4
so basically breaks the pagination and retrieves no result.
I have tried other solutions like adding IF/else statement that if character is null or not equal to range('A','Z') then the $config['base_url'] should have no .$character on the end and the uri_segment should be on 3rd. But it still goes the same as above.
EDIT:
The 2nd problem was solved, i used something like this.
$character = $this->uri->segment(3);
$Alphabet = range('A','Z');
$flag = 0;
for($i=0;$i<26;$i++)
{
if($character==$Alphabet[$i])
{
$flag +=1;
}
}
Seems like, if($character==range('A','Z')) doesnt work as only now noticed when i echoed that range returns results of array so i had to loop. is there any better way to check than what ive done above?
With your pagination config, you have the pagination segment set to 4 regardless of the whether a letter is specified or not. But it should be 3 when there is no character if I'm understanding correctly.
Try something like this:
if(!is_numeric($character)) {
$config['uri_segment'] = 4;
$data['records'] = $this->Model->get_records_filtered($character,$config['per_page'],$this->uri->segment(4));
} else {
$config['uri_segment'] = 3;
$data['records'] = $this->Model->get_records($config['per_page'], $this->uri->segment(3));
}
$this->pagination->initialize($config);
For checking for a character in the range, you can use
if (in_array(strtoupper($character), range('A', 'Z'))
The strtoupper() is optional. Leave it in if you want 'a' to match 'A'.

codeigniter pagination url with get parameters

I am having trouble setting up pagination on codeigniter when I pass parameters in the URL
if my url is like this : search/?type=groups
what should be my $config['base_url'] for pagination to work?
if i set the base url to search/?type=groups the resulting url is search/?type=groups/10
which means $_GET['type']=groups/10
thank you
In pagination config:
if (count($_GET) > 0) $config['suffix'] = '?' . http_build_query($_GET, '', "&");
Your current $_GET vars will be shown in pagination links.
You can replace $_GET by another associative array.
This won't add a query string unless one already exists.
Update:
I just saw, if you go back from another pagination number to click on the first(1), CI does not care anymore of your suffix config.
To fix that use $config['first_url'].
e.g: $config['first_url'] = $config['base_url'].'?'.http_build_query($_GET);
The most up-to-date answer of this question is;
You should enable the reusage of the query string by enabling this configuration:
$config['reuse_query_string'] = true;
after that you should initialize the pagination:
$this->pagination->initialize($config);
Added $config['reuse_query_string'] to allow automatic repopulation
of query string arguments, combined with normal URI segments. - CodeIgniter 3.0.0 Change Log
Here is my jquery solution:
Just wrap pagination links in a div like this:
$config['full_tag_open'] = '<div id="pagination">';
$config['full_tag_close'] = '</div>';
than add the following jquery code:
$("#pagination > a").each(function() {
var g = window.location.href.slice(window.location.href.indexOf('?'));
var href = $(this).attr('href');
$(this).attr('href', href+g);
});
Works fine for me.
if you are using codeigniter 2 there's an option in config.php, $config['allow_get_array'] - make sure its on TRUE.
Then set the pagination option $config['page_query_string'] to TRUE.
And finally, in your case set $config['base_url'] to "search/?type=groups", the pagination will append the per_page query string after it.
It should work this way, you'll get the offset in $this->input->get("per_page").
code strong!
I struggled with the same issue today. My solution is this:
Generate the pagination links and store them in a string ( $pagination = $this->pagination->create_links(); )
Use regexp to find all links and add query strings
The regular expression code used is:
<?php
$query = '?myvar=myvalue';
$regexp = "<a\s[^>]*href=(\"??)([^\" >]*?)\\1[^>]*>(.*)<\/a>";
$unique = array();
if( preg_match_all("/$regexp/siU", $pagination, $matches) )
{
foreach ( $matches[2] as $link )
{
if ( !isset($unique[$link]) )
{
$data['pagination'] = str_replace($link . '"', $link . $query . '"', $data['pagination']);
$unique[$link] = '';
}
}
}
unset($unique);
Works like a charm for me! What it does is:
Find all links
Replace unique links (since there is a previous/next links same link may appear more than once) with the original link and the query-string.
Then just assign the variable to the template that will be shown and use print $your_pagination_variable_name; to show the links with your query-strings attached!
I think you are trying to do the same thing I was trying to do and I got it to work correctly by not setting a base url and just using this setup it kept me from having to manually editting the library
$this->load->library('pagination');
$config['use_page_numbers'] = TRUE;
$config['page_query_string'] = TRUE;
$config['total_rows'] = 200;
$config['per_page'] = 20;
$this->pagination->initialize($config);
Using the $config['suffix'] is the IMO best way to implement this because it doesn't require any extra processing as the regex solution. $config['suffix'] is used in the rendering of the urls in the create_links function that's part of the system/libraries/Pagination.php file so if you set the value it'll be used in the generation of the urls and won't require anymore processing which means it'll be faster.
Thanks for the post, this saved me tons of extra, not needed, coding!
Before line:
$this->base_url = rtrim($this->base_url).'&'.$this->query_string_segment.'=';
Replace this code below:
if(isset($_GET[$this->query_string_segment]))
{
unset($_GET[$this->query_string_segment]);
}
$uri = http_build_query($_GET);
$uri = empty($uri) ? '?' : $uri . '&';
$this->base_url = rtrim($this->base_url).$uri.$this->query_string_segment.'=';
Just see this link.
Just update the modified pagination class and then add
$config['get'] = "?string=" . $_REQUEST['string']."&searchBy=" . $_REQUEST['searchBy'];
The solution is that CodeIgniter does not function like that.
what I need is a method ( in the controller ) for each one of the options in "type"
so one option would be a method called :groups , another called entries etc etc
each method refers to a different model class or method as needed.
I am trying to better understand OOP and CI ...a bit of adjusting to do ... feel free to comment and correct me if i am wrong.
thank you
I got the same problem. My solution is to modify Pagination and put it in application/libraries.
First i create
var $get='';
and find all "a" elements and add $get in the href="........'.$this->get.'"'>.......</a>
Now in the controller or model input these line
$config['get']=(isset($_GET['search']))?'?search='.$_GET['search']:'';
That's it! i hope it will help you.
IN YOUR CONTROLLER:
$config['anchor_class'] = "class='link-pagination'";
IN YOUR VIEW:
$(".link-pagination").each(function() {
$(this).attr("href", $(this).attr('href') + "?id=<?= $this->input->get('id') ?>");
});
Had the same problem but realized that newer versions of CI have a suffix defined within the pagination class. Though it's still not in the documentation. No need to hack it.
I have encountered with similar kind of problem, and based on the above answer here is what I have to do for customization according to my needs.
My URI was to be something like this:
base_url() . /search/?term=
So, here is what I have done:
$config['base_url'] = base_url ."/search/?term=" . $_GET['term']
Hope you'll find the answer on this page:
LINK. Edit your answer back in if you can.

Categories