Need understanding $config["uri_segment"] related code in CodeIgniter - codeigniter

Hey CodeIgniter developers I am new in codeIgniter please see my code related to pagination. Pagination is working fine. I just need your help to understand few lines of code, please see the commented lines in code where I just need your help to understand it.
public function example1() {
$config = array();
$config["base_url"] = base_url() . "welcome/example1";
$config["total_rows"] = $this->services->record_count();
$config["per_page"] = 10;
$config["uri_segment"] = 3; // Need help on this line
$config["next_link"] = '>';
$config["prev_link"] = '<';
$this->pagination->initialize($config);
// Need help on this if condition blocks
if ($this->uri->segment(3)) {
$page = ($this->uri->segment(3));
} else {
$page = 1;
}
$data["results"] = $this->services->fetchServicesByPagination($config["per_page"], $page);
$data["links"] = $this->pagination->create_links();
$this->load->view("example1", $data);
}

Agree With Javier Larroulet
From the Codeigniter documentation $config['uri_segment'] defines what URI segment will contain the page number. It defaults to 3, but you may use another segment if you need. The $this->uri->segment(3) condition on the if clause is checking if the URI Segment number 3 (first after the method name) is set or not. If it is set, use its value as page number, otherwise, default to page 1. Reference

Related

When I click to the next number on pagination, Link active still at number 1

My controller function
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class News extends CI_Controller {
public function __construct()
{
parent::__construct();
$this->load->model('news_media');
$this->load->library('pagination');
}
public function index()
{
$config['base_url'] = base_url()."secret/news/index";
$config['total_rows'] = $this->news_media->getCount();
$config['per_page'] = 3;
$this->pagination->initialize($config);
$page = ($this->uri->segment(4))?$this->uri->segment(4):0;
$data = array();
$data['allnews'] = $this->news_media->get($config['per_page'],$page);
$data['links'] = $this->pagination->create_links();
$html = array();
$html['title'] = "Setting";
$html['head'] = $this->load->view('secret/template/header',null, true);
$html['top'] = $this->load->view('secret/template/top',null, true);
$html['menu'] = $this->load->view('secret/template/menu',null, true);
$html['content'] = $this->load->view('secret/news/news',$data, true);
$html['js'] = $this->load->view('secret/template/js',null, true);
$this->load->view('secret/template/template',$html);
}
}
Problem is that I have pagination 1,2 and in every page I display 3 items.
When I click second page link active still in number 1. How to fix its?
Thank before
Add uri_segment in you pagination config settings:
$config['base_url'] = base_url()."secret/news/index";
$config['total_rows'] = $this->news_media->getCount();
$config['per_page'] = 3;
$config["uri_segment"] = 4;
$this->pagination->initialize($config);
Hope this will help you to resolve this problem. Take a look on documentation that explain it.
$config['uri_segment'] = 3;
The pagination function automatically determines which segment of your URI contains the page number. If you need something different you can specify it.

Is it possible to have the same CodeIgniter URI segment as a function parameter and a pagination parameter?

I've got a method news() which takes two optional parameters - $category & $slug.
The news page needs to show a paginated list of all of the uncategorised news articles (the Category page (with $category set) will need to do the same, but for the categorised subset).
Because of this, it seems that the standard pagination isn't working, as the 2nd URI segment is being seen as the $category parameter for news(). Is it possible to work around this, perhaps treating the 2nd URI segment as the $category parameter if it isn't an integer, or the pagination parameter if it is?
Here are the relevant code pieces:
Controller
function news($category = null, $slug = null) {
if($category == null) { // Get the standard "news" page
// Define the pagination config
$config = array();
$config['base_url'] = base_url() . 'news/';
$config['total_rows'] =$this->post_model->count_posts('NWS');
$config['per_page'] = 3;
$config['uri_segment'] = 2;
$config['use_page_numbers'] = TRUE;
$this->load->library('pagination');
$this->pagination->initialize($config);
// Set the page info
$page = ($this->uri->segment(2)) ? $this->uri->segment(2) : 0;
$data['newsPosts'] = $this->post_model->get_post_list_excerpt('NWS',$config['per_page'], $page);
$data['links'] = $this->pagination->create_links();
$this->template->load('default', 'newsview', $data);
}
elseif($slug == null) {
// Get the page specific to the chosen category
}
}
To try and tidy up the URLs, I'm also using routing:
routes.php
$route['news'] = 'site/news';
$route['news/(:any)'] = 'site/news/$1';
$route['news/(:any)/(:any)'] = 'site/news/$1/$2';
Is there a way round what I'm trying to do/is it even possible? I'd like to avoid having to have separate methods/controllers (such as news/categories/$category if possible
OK, this is some advice that you can consider.
You could use base_url("site/news/"); instead of base_url() . 'news/'; to give clarify to your code.
Make use of news/(:any)/(:any) regex at this case is ambiguous/incorrect because the first (:any) pattern is already containing all the rest of the url. What I mean:
example.com/site/news/12/file
$route['news/(:any)'] = 'site/news/$1';
$1 will match 12/file
$route['news/(:any)/(:any)'] = 'site/news/$1/$2';
$1 will match: 12/file
$2 will match: (nothing)
Might you can conside to use some specific wildcard and give extra security to your urls:
Note: Remember to apply the rules from longest to shortest:
$route['news/(:num)/([a-z]+)'] = 'site/news/$1/$2';
$route['news/(:num)'] = 'site/news/$1';
$route['news'] = 'site/news';
Now, coming back to the original question, I think you could inverse the params to let the category as last one. Let's see:
$config['base_url'] = base_url("news/category/subset");
$config['uri_segment'] = 4;
Take a look at this:
public function news($category = false, $subset = false, $page = 1)
{
$this->load->library('pagination');
//checks if category is the page number
if ((string)(int)$category === $category)
{
//ok, there is not category neither subset
$config['base_url'] = base_url('site/news');
$config['uri_segment'] = 3;
}
//checks if subset is the page number
else if ((string)(int)$subset === $subset)
{
$config['base_url'] = base_url('site/news/' . $category);
$config['uri_segment'] = 4;
}
//by elimination, all the three parameters are presents
else
{
//ok, both are presents
$config['base_url'] = base_url('site/news/' . $category . '/' . $subset);
$config['uri_segment'] = 5;
}
$config['total_rows'] = 200;
$config['per_page'] = 20;
$this->pagination->initialize($config);
// more stuff here
}
This pagination config should works with urls like:
example.com/site/news/
example.com/site/news/cat/
example.com/site/news/cat/subset/
and page numbers:
example.com/site/news/3
example.com/site/news/cat/5
example.com/site/news/cat/subset/3

codeigniter pagination pulling item more then once

This is a very irritating issue. I have my codeigniter pagination set up and so I thought working, but looking at it closer it seems that on the last page it's pulling in previous results to fill the page in.
So say I want ten per page and have fourteen results. The first page has ten results, and so does the second. When it should be the first has ten and the second has four. It would be fine if it was just repeating one result, but it's irritating to have to scroll through six previous results. Any help would be much appreciated.
in my controller I have the pagination code
$config = array();
$config["base_url"] = base_url()."myStories/".$id;
$config["total_rows"] = $this->data_model->my_count();
$config["per_page"] = 10;
$config["uri_segment"] = 3;
$config['num_links'] = 2;
$choice = $config["total_rows"] / $config["per_page"];
//$config["num_links"] = round($choice);
$this->pagination->initialize($config);
$page = ($this->uri->segment(3)) ? $this->uri->segment(3) : 0;
$this->load->view('userStory_view', array(
'query' => $this->data_model->pullMyStories($config['per_page'], $page),
'links' => $this->pagination->create_links(),
'user' => $this->users_model->getUser($this->user->user_id),
));
and then in my model I have the count and then the actual results coming back
public function my_count() {
//This counts all the stories that belong to that author
$author = $this->uri->segment(2);
$this->db->where('author', $author);
$this->db->where(array('approved !=' => 'd'));
$query = $this->db->get('story_tbl');
return $query->num_rows();
}
public function pullMyStories($limit, $start){
//This pulls back all the stories that belong to that author
$this->db->limit($limit, $start);
$this->db->order_by("date", "desc");
$author = $this->uri->segment(2);
$this->db->where(array('approved !=' => 'd'));
$this->db->where('author', $author);
$story = $this->db->get('story_tbl');
return $story->result();
}
the route I have set up that does work
$route['myStories/(:any)'] = "story/viewStories/$1";
I thought initially that my count was count was wrong, but even with a count of 14, 20 results come back.
For further information I am more than positive that my baseUrl is correct. I have modified my .htaccess to get rid of the index.php and have edited my route file to make the controller disappear from the url. To try and make it easy to remember for the user.
I am also very sure that the uri segments are correct. If they were not correct then my page would not be coming up at all.
I have tried all the normal solutions and nothing has worked. That is why I am asking here and why I have placed a bounty on this question.
var $base_url = ''; // The page we are linking to
var $prefix = ''; // A custom prefix added to the path.
var $suffix = ''; // A custom suffix added to the path.
var $total_rows = 0; // Total number of items (database results)
var $per_page = 10; // Max number of items you want shown per page
var $num_links = 2; // Number of "digit" links to show before/after the currently viewed page
var $cur_page = 0; // The current page being viewed
var $use_page_numbers = FALSE; // Use page number for segment instead of offset
var $first_link = 'First';
var $next_link = '->';
var $prev_link = '<-';
var $last_link = 'Last';
var $uri_segment = 2;
var $full_tag_open = '';
var $full_tag_close = '';
var $first_tag_open = '';
var $first_tag_close = ' ';
var $last_tag_open = ' ';
var $last_tag_close = '';
var $first_url = ''; // Alternative URL for the First Page.
var $cur_tag_open = ' <strong>';
var $cur_tag_close = '</strong>';
var $next_tag_open = ' ';
var $next_tag_close = ' ';
var $prev_tag_open = ' ';
var $prev_tag_close = '';
var $num_tag_open = ' ';
var $num_tag_close = '';
var $page_query_string = FALSE;
var $query_string_segment = 'per_page';
var $display_pages = TRUE;
var $anchor_class = '';
Your problem is that you are passing the wrong parameters to your pullMyStories method. On the first page you will be apply the following limit to your query
LIMIT 0,10
Then on the second page
LIMIT 1,10
Then on the third
LIMIT 2,10
So you pagination is only moving forward one item at a time instead of ten. So you need to change this
'query' => $this->data_model->pullMyStories($config['per_page'], $page),
To this
'query' => $this->data_model->pullMyStories($config['per_page'], ($page * $config['per_page'])),
I recently tried so hard to about ci pagination.
I think, your codes right.
What exactly uri string on second page?.. And this listing function is index() ?
Try if it works for you:
$config = array();
$config["base_url"] = base_url()."myStories/"; #change in base url
$config["total_rows"] = $this->data_model->my_count();
$config["per_page"] = 10;
$config["uri_segment"] = 3;
$config['num_links'] = 2;
#$choice = $config["total_rows"] / $config["per_page"];
//$config["num_links"] = round($choice);
$this->pagination->initialize($config);
#$page = ($this->uri->segment(3)) ? $this->uri->segment(3) : 0; #no need of calculation here
$this->load->view('userStory_view', array(
'query' => $this->data_model->pullMyStories($this->uri->segment(3)), #change here send the offset directly
'links' => $this->pagination->create_links(),
'user' => $this->users_model->getUser($this->user->user_id),
));
function pullMyStories($offset = 0){
$story = $this->db->where('author', $this->uri->segment(2))->where('approved != d')->order_by("date", "desc")->get('story_tbl', 10, $offset);
return $story->result();
}
Try this. You just need to change the base_url in the correct way. Also be careful and check if you are getting a right number for uri_segment. If not, you can change the number, and get the correct.
// $config = array();
// MUST CHNGE IT I just tell the with simple example. If you have index.php, c name and method name.
$config["base_url"] = base_url()."index.php/controller_name/function_name/";
$config["total_rows"] = $this->data_model->my_count();
$config["per_page"] = 10;
$config["uri_segment"] = 3; // BE CARFULL with uri_segment. You need to print it, and be shre that you are getting the right number
$config['num_links'] = 2;
$this->pagination->initialize($config);
$page = ($this->uri->segment(3)) ? $this->uri->segment(3) : 0;
$this->load->view('userStory_view', array(
'query' => $this->data_model->pullMyStories($config['per_page'], $page),
'links' => $this->pagination->create_links(),
'user' => $this->users_model->getUser($this->user->user_id),
));
I update my code, I comment and $config = array();
I did it today in my computer this, and it works. I know that you maybe checked it hundred times, but Check in details it again.
UPDATE with my example:
function index() {
$data['page_title'] = "Items";
$config['base_url'] = base_url() .'index.php/items/index/';
$config['total_rows'] = $this->items_model->count_items(); // Count items from DB
$config['per_page'] = 10;
$config['uri_segment'] = 3;
// Customize
$config['next_link'] = FALSE;
$config['prev_link'] = FALSE;
$config['first_link'] = 'first';
$config['last_link'] = 'last';
$config['cur_tag_open'] = '<a class="current">';
$config['cur_tag_close'] = '</a>';
$this->pagination->initialize($config);
$page = ($this->uri->segment(3)) ? $this->uri->segment(3) : 0;
$data['items'] = $this->items_model->get_items($config["per_page"], $page);
$this->load->view('invoice-items', $data);
}
In your controller:
$page = $this->uri->segment(3,0);
Then:
public function pullMyStories($limit, $start){
$author = $this->uri->segment(2);
$this->db
->select('*')
->where('approved !=', 'd')
->where('author', $author)
->order_by('date', 'DESC')
->limit($limit, $start);
$story = $this->db->get('story_tbl');
return $story->result();
Also where do you load the library using the line below?
$this->load->library('pagination');
I'm just gonna throw this in and hope it helps in some way, because I've tested and it works for me. I've made the following assumptions for testing:
id (as in "myStories/".$id in the controller) is taken from $this->uri->segment(2)
story_tbl fields I created were id, author, date
My test files were as follows:
Controller MyStories.php:
public function index()
{
//loading library, model, and assumptions
$this->load->library('pagination');
$this->load->model('m_page', 'data_model');
$id = $this->uri->segment(2);
//
//
//Your code from here...
//
//
$config = array();
$config["base_url"] = $this->config->site_url("myStories/".$id);
$config["total_rows"] = $this->data_model->my_count();
$config["per_page"] = 3;
$config["uri_segment"] = 3;
$config["num_links"] = round($config["total_rows"] / $config["per_page"]);
$this->pagination->initialize($config);
$page = ($this->uri->segment(3)) ? $this->uri->segment(3) : 0;
$data = array();
$data['query'] = $this->data_model->pullMyStories($config['per_page'], $page);
$data['links'] = $this->pagination->create_links();
$data['config'] = $config;
//$data['user'] = $this->users_model->getUser($this->user->user_id);
$this->load->view('userStory_view', $data);
}
BTW, you really want to be using the site_url and not base_url when defining the pagination base_url.
I also commented out the 'user' data in the controller simply because you never gave any info on that.
My test view, userStory_view.php:
<?php echo $links;?>
<!-- -->
<hr>
total rows: <?php echo $config['total_rows'];?>
<hr>
<?php echo $this->db->last_query();?>
<hr>
<!-- -->
<?php foreach ($query as $row):?>
<?php echo $row->author.'<hr>';?>
<?php endforeach;?>
I made no changes to your Model, so no need to show that here.
I added the following line to routes.php:
$route['myStories/(:any)'] = "myStories";
As I said, everything worked for me. Besides my formatting, the only changes I really made were the use of site_url() instead of base_url(), and the commenting of the user data. So pretty stuck as to why you're having issues I'm afraid.
As far as it seems your overall pagination functionality seems to correct. what i want check would the sql query returned in each function and parameters passed to those function coz $author variable has to global and try
$this->db->last_query();
on your both functions my_count() and pullMyStories($limit, $start) and check those function returning right results.
U might also can try writing direct sql query with changing parameters like.
$sql = "SELECT * FROM some_table WHERE author = ? LIMIT ?, ?";
$this->db->query($sql, array($author, $start, $limit));
As i am seeing this would be mostly of query might have been wrong .
Hope this helps.

Codeigniter Pagination having page number in the middle of url

I'm trying to use pagination class in codeigniter and my url looks something like this:
blah.com/posts/browse/page/1/item_per_page/10
is there anyway to keep the page number in the middle of url?
Thanks
EDIT:
$this->load->library('pagination');
$uri = $this->uri->uri_to_assoc();
$page = null;
$item_per_page = null;
if (count($uri))
{
foreach ($uri as $key => $value)
{
$$key = $value;
}
}
$config['base_url'] = base_url('posts/browse/page//item_per_page/1');
$config['uri_segment'] = 4;
$config['per_page'] = '1';
After digging through code of Pagination class, I found a way to do this, but it wasn't mentioned anywhere in the tutorial.
$config['base_url'] = base_url('posts/browse');
$config['prefix'] = '/page/';
$config['suffix'] = '/item_per_page/1';
$config['uri_segment'] = 4;
this can generate urls with page number in the middle of the url.
eg. http://www.blah.com/posts/browse/page/2/item_per_page/1;
The documentation clearly explains how to do this.
Short version: use $config['uri_segment'] = 4; in your pagination config. uri_segment tells the pagination class which uri segment contains the page #.

pagination doesn't work in codeigniter

I have successfully created pagination on some of the pages on the application on which I am working with, but I can't make it on this one:
I have 7 records in the database, and when
page is displayed all 7 records are displayed instead of 5, as I would like to be.
Sure enough, links for the paging are not displayed.
Here is my controller code:
public function displayAllFaqCategories()
{
//initializing & configuring paging
$currentUser = $this->isLoggedIn();
$this->load->model('faqCategoriesModel');
$this->db->order_by('sorder');
$limit = 5;
$offset = 3;
$offset = $this->uri->segment(3);
$this->db->limit(5, $offset);
$data['faq_categories'] = $this->faqCategoriesModel->selectCategoriesAndParents();
$totalresults = $this->db->get('faq_categories')->num_rows();
//initializing & configuring paging
$this->load->library('pagination');
$config['base_url'] = site_url('/backOfficeUsers/faqcategories');
$config['total_rows'] = $totalresults;
$config['per_page'] = 5;
$config['uri_segment'] = 3;
$this->pagination->initialize($config);
$errorMessage = '';
$data['main_content'] = 'faq/faqcategories';
$data['title'] = 'FAQ Categories';
$this->load->vars($data,$errorMessage);
$this->load->vars($currentUser);
$this->load->view('backOffice/template');
} // end of function displayAllFaqCategories
And here is my model function code:
public function selectCategoriesAndParents($selectWhat = array())
{
$data = array();
$query = $this->db->query("SELECT fq . * , COALESCE( fqp.$this->parent_name, '0' ) AS parentname
FROM $this->table_name AS fq
LEFT OUTER JOIN $this->table_name AS fqp ON fqp.catid = fq.parentid");
if($query->num_rows() > 0)
{
foreach($query->result_array() as $row)
{
$data[] = $row;
}
}
$query->free_result();
return $data;
} // end of function selectCategoriesAndParents
In the view, bellow of the table with the records I have the following code:
<?php echo $this->pagination->create_links();?>
Any help will be deeply appreciated.
Regards,Zoran
You've mixed two different things together I think. You're partially using the ActiveRecord class of CI, but then running the query yourself.
The simplest change would be:
// get all the rows
$data['faq_categories'] = $this->faqCategoriesModel->selectCategoriesAndParents();
// figure out the count of all of them
$totalresults = count($data['faq_categories']);
// only take some of the rows of the array, instead of keeping all of them and then showing all 7 of your records
$data['faq_categories'] = array_splice($data['faq_categories'], $offset, $limit);
Hopefully that should fix it!
To further explain what the original problem is, I think when you run this:
$totalresults = $this->db->get('faq_categories')->num_rows();
It takes the previous line $this->db->limit(5, $offset); into account, so it only returns 5 rows. Then, when you tell the pagination library that you only want to show 5 per page, the library thinks that it is actually showing all the results, so there is no need for pagination links!
Edit like this
$offset = $this->uri->segment(3) ? $this->uri->segment(3) : 0;

Resources