inconsistent amount of data when I use pagination in CodeIgniter - php

I want to perform a large of data using paging library in CodeIgniter. I have been implementing it and it works. But, I have a problem - amount of data per page is not consistent.
This is the simple code how Imade it...
Controller
class Buku_con extends Controller {
public function Buku_con() {
parent::__construct();
$this->load->model('buku_model');
$this->load->library('pagination'); //call pagination library
}
function getBuku() {
//count the total rows of tb_book
$this->db->select('*');
$this->db->from('tb_book');
$getData = $this->db->get('');
$a = $getData->num_rows();
$config['base_url'] = base_url().'index.php/Buku_con/getBuku/'; //set the base url for pagination
$config['total_rows'] = $a; //total rows
$config['per_page'] = '10'; //the number of per page for pagination
$config['uri_segment'] = 3; //see from base_url. 3 for this case
$config['full_tag_open'] = '<p>';
$config['full_tag_close'] = '</p>';
$this->pagination->initialize($config); //initialize pagination
$data['detail'] = $this->buku_model->getBuku($config['per_page'],$this->uri->segment(3));
$this->load->view('buku_view', $data);
}
}
Model
class Buku_model extends Model {
function Buku_model() {
parent::Model();
}
function getBuku($perPage,$uri) { //to get all data in tb_book
$title=$this->session->userdata('title');
$this->db->select('*');
$this->db->from('tb_book');
$this->db->where('title','$title');
$this->db->order_by('id','DESC');
$getData = $this->db->get('', $perPage, $uri);
if($getData->num_rows() > 0)
return $getData->result_array();
else
return null;
}
}
View
if(count($detail) > 0) {
//... html for table .....
foreach($detail as $rows) {
echo
.... $rows['id'] .....
.... $rows['title'] .....
.... $rows['author'] .....
....
}
echo $this->pagination->create_links(); ....
The paging works well, but amount of data per page is not consistent like I define in controller. I think the problem is caused by the query that I use in model - Session of title.
I want the data perform 10 data per page, but in page 1 just 5 data, page 2 just 4 data - not consistent. Maybe the problem is also in the view. What should I do? Thank you very much.

you have not properly calculated the offset. You may try this:
$offset = ( $this->uri->segment(3) - 1 ) * $config['per_page'];
$data['detail'] = $this->buku_model->getBuku($config['per_page'], $offset);

you might wanna look at this for proper pagination using codeigniter Pagination Library
https://stackoverflow.com/a/10123424/876117
You don't get all the data for each request. You need to fetch only data as specified the offset in the link generated by the pagination library.

Dude, there is a lot of queries on your Controller. And also on Model (of corse).
First: Try to consume almost only functions on your controller. Functions that you create on a model. Thats is the right MVC way.
And about your problem with pagination:
Try to use and abuse of GET variables. Kind, you can pass a url like that:
http://site.com/controller/function?p=2
See? "?p=2"? That way I can say to my controller that I want to see the second page os the list. You know, I can pass more GET variables, like:
http://site.com/controller/function?p=2&cat=romance&year=2010
And theres the way you will work these variables:
Lets take the second exemple ("?p=2&cat=romance&year=2010")
$page = $this->input->get('p'); // this is more secure too. avoid use $_GET or $_POST
$category = $this->input->get('cat');
$year = $this->input->get('year');
Now you can use some functions to get a list of books that matches to the values:
$data['books'] = $this->book->get_by_search($page, $category, $year);
PS: On this example, you got load a model 'book'that holds a function called 'get_by_search'. You have to do it to get the code working.
Tip: We never know how many variables a search can get. So you can create some model functions that receives those possible variables. Look:
//model Book
public function get_by_search($page = NULL, $cat = NULL, $year = NULL, $author = NULL)
{
$perpage = 10;
// the NULL is to prevent an error if the function is called without them.
if ( ! is_numeric($page) || $page < 0)
{
$qtd = $perpage;
$offset = 0;
}
else
{
$qtd = $page * perpage;
$offset = $perpage;
}
$this->db->where('category', $cat);
$this->db->where('year', $year);
return $this->db->get('books', $perpage, $offset);
// if you want to debug your queries, do the same above, but with no return
// and then use this:
echo this->db->last_query(); die; // stop here and see the query string.
}
well, I hope that it can help you. There is more to tell you but I think that its better you tell me more about your progress with the code. This answer is just a part of the solution. See? thats is not that simple, but I know how. Let me know here if you need more help, ok?
Um abraço!

Related

Is it possible to implement Laravel pagination on a custom foreach

I have set of Ids as an array. It is out put of a complex search logic. For example my array is :
array(2,5,1,8,9,12,83,32);
Each of these IDs are valid and represents posts. So what I do is I just loop them in a for each loop and collect all data to a final array. Example :
foreach($ArrayOfIds as $id)
{
$posts[] = Post::findOrFail($id);
}
then I send this $posts to my view. Is it possible to implement laravel pagination in this scenario.? Keep in mind that I can't play any more with $ArrayOfIds.
Yes it's possible, example using Illuminate\Pagination\LengthAwarePaginator
public function showPost()
{
$posts = [];
foreach($ArrayOfIds as $id) {
$posts[] = Post::findOrFail($id);
}
$perPage = 6;
$paginator = new LengthAwarePaginator($posts, count($posts), $perPage);
$items = $paginator->getCollection();
return $paginator->setCollection(
$items->forPage($paginator->currentPage(), $perPage)
);
}
At first, I instantiate LengthAwarePaginator class and feed it with the arguments needed, see here. And then, as I need to set which posts belongs to which page, I then use forPage method from Illuminate/Support/Collection.
Something like that.

Laravel Custom Pagination

Having problems getting my pagination to work in Laravel 5.2 I use a foreach to generate a list of objects where each object has a certain ranking. (competition)
The first query I used was this one:
$goedeDoelen = GoedDoel::orderBy('punten', 'desc')->simplePaginate(5);
This worked pretty ok, only problem was that my ranking would reset everything I would go to a different page.
Example: Page 1 has objects from rank 1 - 5, page 2 should have ranks 6-10. By using the first Paginate method, the second page would have objects starting from 1 again.
I have tried to work around this by adding the ranking as an extra attribute to my Eloquent collections.
$ranking = GoedDoel::orderBy('punten', 'desc')->get();
foreach($ranking as $key => $item) {
$item->ranking = $key+1;
}
After that I tried to use ->simplePaginate() on my updated collection. This gave an error.
I have created a custom Paginator.
$goedeDoelen = new Paginator($ranking, 5);
This isn't working as intended. When I go to my second page, the URL messes up and goes to another view.
How can I make sure the Paginator knows what my current URL is to which it has to apply the ?page=2
You need to use the paginate() method.
$goedeDoelen = GoedDoel::orderBy('punten', 'desc')->paginate(5);
{!! $goedeDoelen->links() !!}
The following Code illustrates manual pagination in Laravel
Sample Controller
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator as Paginator;
use App\Models\UserRechargeDetails;
class PaginateController extends Controller
{
//
public function index(Request $request)
{
$user_1 = new UserRechargeDetails;
// Get records from Database
$items = $user_1->all();
// Store records in an array
$records = [];
$i = 0;
foreach($items as $item)
{
$records[$i][0] = $item->user_name;
$records[$i][1] = $item->rech_mobile;
$i++;
}
// Current page for pagination
$page = $request->page;
// Manually slice array of product to display on page
$perPage = 2;
$offset = ($page-1) * $perPage;
$data = array_slice($records, $offset, $perPage);
// Your pagination
$final_data = new Paginator($data, count($records), $perPage, $page, ['path' => $request->url(),'query' => $request->query(),]);
/*
For Display links, you may add it in view page
{{ $data->links('pagination::bootstrap-4') }}
*/
return view('admin.pagination_new', ['data' => $final_data, 'j' => 1]);
}
}

How to make pagination in view by using the array variable from controller in laravel

I'm new to Laravel and I can't understand the pagination concept for an array passed from the controller to the view.
My view code
#foreach($aHotelRooms as $aHotelRoom)
<?php
//display contents
?>
#endforeach
Here, I would like to set pagination using $aHotelRooms.
I dont know how to use $users = DB::table('table_name')->paginate(3); and echo $users->render(); for my $aHotelRooms..
Please someone help me..
I dont know how to use...
paginate(3) will create collection where you'll have just 3 rows from your DB. Then $users->render(); will create HTML pagination code. You must use $users->render(); in hte view. You do not need to use #foreach or something like that to build pagination.
Example:
In controller:
$aHotelRooms = AHotelRoom::paginate(10);
return view('myview', compact('aHotelRooms'));
In the myview.blade.php:
$aHotelRooms->render();
I finally ended up with this solution.And it works for me great.
Controller
use Illuminate\Pagination\LengthAwarePaginator as Paginator;
use DB;
public function postHotelresults(Request $request,$page = 1)
{
.
.
.
$sqlCond = 'WHERE 1 '.$this->getAreaCondition($_POST['search_city']);
.
.
$query = "SELECT `h`.*,".$countquery.",".$minquery." FROM `abserve_hotels` as `h`";
$query1 = DB::select($query.$sqlCond);
$perPage = 2;
$currentPage = Input::get('page', 1) - 1;
$pagedData = array_slice($query1, $currentPage * $perPage, $perPage);
$query1 = new Paginator($pagedData, count($query1), $perPage);
$query1->setPath('hotelresults');
.
.
return view('hotel.list', $this->data,compact('query1'));
}
Here,setPath('hotelresults') leads to my function while clicking my links in pagination
View
<?php
if(!empty($query1)){
?>
#foreach($query1 as $aHotelRoom)
{{$aHotelRoom->hotel_id }}
{{$aHotelRoom->logo}}
#endforeach
<?php
echo $query1->render();
}
Here,I found one thing that when we would like to pass the array from the controller we should use $query1 = DB::select(...) to write query and return view('hotel.list',compact('query1')); for passing that query as in array format to the view.
It might useful for someone...

Paginator Symfony advice for making query

I am trying to make a paginator in Symfony and this is how my code looks like:
Controller class:
class MovieDisplayController extends Controller
{
public function showAction()
{
//Records:
//$movies = $this->getDoctrine()->getEntityManager()->getRepository('AppBundle:Movie')->FindAll();
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery(
'SELECT m
FROM AppBundle:Movie m'
)->setMaxResults(5)->setFirstResult(0);
$movies = $query->getResult();
//$resultAmount = $query->getResult()-count();
//Pagination:
$filterVariables = "";
$currentPage = (isset($_GET['page'])) ? $_GET['page'] : 1;
$totalPages = /*Example: */20; //something like: $this->count($movies) / $recordsPerPage
return $this->render('movies/index.html.twig', array(
'movies' => $movies,
'filtervariables' => $filterVariables,
'page' => $currentPage,
'totalPages' => $totalPages
));
}
}
This code works perfectly fine, however I want to make my paginator work and I have to pass some GET variables in the LIMIT part of a query (at least that is what I found out after doing some searching).
First of all, let me ask if any of you would know, the use of the GET variables in the "pagination" part of the class, would that be the proper way in Symfony to call those? I have seen something like: $foo = $request->query->get('page'); but that does not seem to return anything (or at least not the same as the $_GET['page'] variable), or am I trying to do something that is not possible (anymore)?
(Also I do not wish to make use of routing for this)
Secondly I would like to know if it is possible (or how) to count the amount of results I would get by using $movies = $query->getResult().
If anyone has any tips or advice for me to optimize my code and make it working, I would gladly want to know.
Edit: My pagination works fine now, if there should be any tweaks to make it even work more perfectly, feel free to add a comment or an answer if it's an important change. (Code used)
Thanks in advance.
GET and SET variables within symfony
There are several possibilities how to pass variables to controller. The simplest will be to use the routing.
/**
* #Route("something/{page}/{limit}", defaults={"page" = 1, "limit" = 10}, name="show_action")
*/
public function showAction($page, $limit)
{
}
Then you will be able to use $page and $limit directly inside your controller.
If you don't want to use routing you may also use session instead:
public function showAction(Request $request)
{
$this->get('session')->get("page");
$this->get('session')->get("limit");
}
Counting records
You may count your sql records using DQL:
$query = $this->createQueryBuilder()
->from('Movie', 'f')
->getQuery();
$total = $query->select('COUNT(f)')
->getQuery()
->getSingleScalarResult();

Sorting does not work on 2nd page of pagination

I was trying to list using pagination in Codeigniter. I was willing to use sorting in the list by using jquery ajax. It works perfectly for first page of pagination. I could do ascending and descending sorting in that page. But when i click on other page. It does not work.
What could be the problem. Can any one suggest me??
Thanks in advance.
This is the code for my controller
function listData(){
$this->clear_sample_id_catche();
$out=$this->Mgeneral->listData();
$per_page = 10;
$total = $this->Mgeneral->countData();
$data = $this->Mgeneral->listData($per_page, $this->uri->segment(3));
$base_url = site_url('general/listData');
$config['base_url'] = $base_url;
$config['total_rows'] = $total;
$config['per_page'] = $per_page;
$config['uri_segment'] = '3';
$this->pagination->initialize($config);
$data=array('body'=>'list','out'=>$data);
$this->load->view('template',$data);
}
This is for my model
function listData($limit = NULL, $offset = NULL)
{
$this->db->limit($limit, $offset);
$data=array();
$q=$this->db->get('tbl_sample_id');
if($q->num_rows()>0)
{ $data=$q->result_array();
return $data;
}
}
and i have use ajax as
<script type="text/javascript">
$(document).ready(function(){
$("#internal").click(function(){
$.ajax({url:"general/listData_internal_ascending",success:function(result){
$("body").html(result);
}});
});
});
Thank you
Pagination uses the Limit and the Offset parameters when making the database calls. If you're using pagination, then clicking the page links will pass back the Offset. If this is working for you so far, then all you need to do is make sure that you keep the Sort parameter somewhere in your page.
If your controller method is checking for the GET variable to find the offset for the pagination, you need to make sure that the method also knows which field to sort by. I personally store it in flashdata.
So in your controller methood, before the db call:
$SortColumn = $this->session->flashdata('SORT_BY');
If there's no Sort saved there, then it returns false, so you can check for that when adding your $db->order_by() method. If there is something there, then you can sort appropriately.
Then right at the bottom of the method before the view gets loaded, set the Sort back to flashdata so the next time the method is called (on next page request), it has the Sort field to work with again.
$this->session->set_flashdata('SORT', $SortColumn);
Sorry I don't have any full code examples, as I use PHP-ActiveRecord instead of the CI built-in activerecord library.
You function should look like this
function listData($limit = NULL, $offset = NULL)
{
$this->db->limit($limit, $offset);
$this->db->order_by('id');
$q = $this->db->get('tbl_sample_id');
if($q->num_rows()>0)
{
return $q->result_array();
}
}
I can suggest you to pass sorting parameters in your ajax call of pagination . that could be the problem.

Categories