I'm really lost on how pagination works in kohana 3. Is there a good example of pagination in Kohana 3 anywhere?
// Get the total count of articles
$count = $this
->_profil
->articles
->count_all();
// Create the pagination object
$pagi = Pagination::factory(array(
'items_per_page' => 4,
'total_items' => $count,
));
// Find actual articles
$articles = $this->_profil
->articles
->join_categories()
->order_by('id','DESC')
->limit($pagi->items_per_page)
->offset($pagi->offset)
->find_all();
and then in the View, you just do
echo $pagi; // ofc, after passing the Pagination object to view
What happens here is Pagination class using it's View's __toString() magic method to render html needed to display pagination. All pagination params can be modified when creating the object (passing appropriate keys to the array passed to factory() method in our case).
Default key for pagination is "page" (query string), while you can modify that as well. Pagination also has a default config, which you can override by copying it to application/config folder.
Enjoy using it :)
In Kohana 3.1 pagination is not included. Download the module and put it in the modules folder. Enable the module in your application/bootstrap.php .This is my controller page. For further configuration copy the provided config file from modules/pagination/config/pagination.php to application/config/pagination.php
$per_page =2;
$page_num = $this->request->param('page', 1);
$offset = ($page_num - 1) * $per_page;
$view =View::factory('image/imagelist')->bind('page_links',$page_links)->bind('results', $results)->bind('pagination', $pagination);
// Get the total count of records in the database
$userid = Auth::instance()->get_user()->pk();
$count=ORM::factory('user_image')->where('app_userid','=',$userid)->count_all();
// Create an instance of Pagination class and set values
$pagination = Pagination::factory(array(
'total_items' => $count,
'current_page' => array('source' => 'image/imagelist', 'key' => 'page'),
'items_per_page' => $per_page,
'offset' => $offset,
'view' => 'pagination/basic'
));
// Load specific results for current page
$results = DB::select()->from('user_images')
->where('app_userid','=',$userid)
->order_by('image_id','ASC')
->limit($pagination->items_per_page)
->offset($pagination->offset)->execute();
$page_links = $pagination;
$this->template->content=$view->render();
You may get error ErrorException [ Notice ]: Undefined property: Request::$uri. in the pagination class (module). In order to fix fix it
Use Request::current()->uri() instead of Request::current()->uri
You can find some decent docs in the unofficial Kohana wiki.
Related
I switched over to Opencart 3.0.. Not to fond of the .tpl to .twig changes.
Anyways, I have been trying, to no avail, to display all products from a particular category on another category page.
I found this foreach loop:
{% for product in products %}
Which I imagine reads
<?php foreach ($products as $product) { //do something } ?>
I tried adding the Loop to the path:
catalog/view/theme/*/template/product/category.twig
but it only shows the products from the current category page id I am currently on.
Any help would be greatly appreciated.
It's generally bad practise on OC to edit the files directly, rather look at OCMOD or VQMOD to make runtime changes but not edit the core file. Granted this may be an additional complication right now.
If you look at the category.php file in the /catalog/controller/product/ folder around line 150, you'll see these lines of code:
$data['products'] = array();
$filter_data = array(
'filter_category_id' => $category_id,
'filter_filter' => $filter,
'sort' => $sort,
'order' => $order,
'start' => ($page - 1) * $limit,
'limit' => $limit
);
$product_total = $this->model_catalog_product->getTotalProducts($filter_data);
$results = $this->model_catalog_product->getProducts($filter_data);
What you need to do is create a new $filter_data variable with your requisite filters, you can just have the category ID if that's all you need.
Look at the line below:
$results = $this->model_catalog_product->getProducts($filter_data);
It's calling the method getProducts which is located in the model CatalogCategory (/catalog/model/product.php) this method will build a SQL query based on the filters passed to the method and return an associative array with the results (hence the aptly named $results variable).
The controller file we first looked at then iterates through these $results and stores the values in $data['products'].
Putting this together, you can try the following:
$data['products2'] = array();
$new_filter_data = array(
'filter_category_id' => 13 // or any relevant ID
);
$results2 = $this->model_catalog_product->getProducts($new_filter_data);
This isn't a complete solution as the controller file continues to resize images, get reviews etc. So you'll need to adjust this according to what your needs are and play around a little.
Just make sure you're working on a local copy of the site!
I'm using the WP MVC plugin to create a plugin which provides a database of names as part of my Wordpress website.
The below controller retrieves the right information from 2 database tables, but suddenly pagination is not working anymore. Do I need to use paginate() instead of find()? If yes, how would a similar query look using paginate()? Unfortunately there are no examples available.
Thanks!
names_controller.php
<?php
class NamesController extends MvcPublicController {
public function index() {
$objects = $this->Name->find(array(
'joins' => array('Origin'),
'selects' => array('Origin.id', 'Origin.origin', 'Name.id', 'Name.name', 'Name.gender', 'Name.meaning', 'Name.origin_id'),
'page' => 1,
'per_page' => 20,
'conditions' => array(
'Name.name LIKE' => 'A%'
)
));
$this->set('objects', $objects);
}
}
?>
=================== UPDATE ======================
I replaced the find() with paginate() unfortunately the join doesn't work anymore. Furthermore it IGNORES e.g. page, per_page etc parameters.
Anyone an idea?
$params = $this->params;
$params['page'] = empty($this->params['page']) ? 1 : $this->params['page'];
$params['per_page'] = 20;
$params['joins'] = array('Origin');
$params['selects'] = array('Origin.id', 'Origin.origin', 'Name.id', 'Name.name', 'Name.gender', 'Name.meaning', 'Name.origin_id');
$collection = $this->Name->paginate($this->params);
$this->set('objects', $collection['objects']);
$this->set_pagination($collection);
So I've been working on a pagination system that pulls data externally, after finally figuring out through trial and error I got the solution that works. While going through it something struck me as odd, as per the documentation $paginator = Paginator::make($items, $totalItems, $perPage);
I was wondering what's the actual use of the $perPage parameter? You would think that what ever number is specified would show that many items. But with manual pagination you have to limit the results that are passed into $items in order for it to work, otherwise you get the output of all items (as shown in code block below). Is manual pagination flawed? because if $perPage doesn't match the total number of items in the array $items it shows everything.
Example: Paginator::make( array('10xarray') ), 10, 2); it would show 5 pages with 2 items per page? where in reality it actually shows 10 items with 5 pages that all show the same 10 items.
<?php
class MainController extends BaseController {
public function library()
{
$this->layout->title = 'testing';
$this->layout->main = View::make('library/layout');
// Pagination data
$media = array(
array('title' => 'test'),
array('title' => 'test'),
array('title' => 'test'),
array('title' => 'test')
);
$perPage = 2;
$currentPage = Input::get('page', 1);
$pagedData = array_slice($media, ($currentPage - 1) * $perPage, $perPage);
$this->layout->main->paginated = Paginator::make($pagedData, count($media), $perPage);
if(Request::ajax()) {
return Response::json(
View::make(
'library/layout',
array('paginated' => $this->layout->main->paginated)
)->render()
);
}
}
}
it isn't flawed. it is intended behavior.
this manual paginator is just a container. nothing more, nothing less. how you implement it, is upon you.
without a LIMIT query, you can never do a pagination. when you use pagination(), laravel does the work under the hood. when you go for manual, you have to do it manually and get greater control.
why do you think it is called manual pagination in the first place?
I am trying to get the Tags Plugin (https://github.com/CakeDC/tags) to work using the find by method (pagination) as outlined at the following example:
https://github.com/CakeDC/tags/wiki/Find-tagged-objects
The tags seem to be setup and working as I can add tags to my 'items' model but I cannot search by.
I have my code as follows (function index):
if (isset($this->passedArgs['by'])) {
$this->paginate['Tagged'] = array(
'model' => 'Item',
'tagged',
'by' => $this->passedArgs['by']);
$items = $this->paginate('Tagged');
} else {
$this->Item->recursive = 1;
$items = $this->paginate();
}
$this->set('items', $items);
$this->set('tags', $this->Item->Tagged->find('cloud', array('limit' => 10)));
When I click though from my tags cloud I get this error:
Indirect modification of overloaded property ItemsController::$paginate has no effect [APP/Controller/ItemsController.php, line 20]
Line 20 is: $this->paginate['Tagged'] = array(
Any idea where I am going wrong?
Thanks
The issue was I needed to setup paginate in the controller first.
public $paginate = array();
I want to do something very straight forward and simple. I want to have two different sets of paginated data on the same page. The two different sets depend on different models. For discussion's sake we'll say they are Image and Item.
I can set up two pagers for two models, and get the correct set of objects. I can get the correct pager links. But when it comes to actually following the links to the parameters, both pagers read the parameters and assume they apply to them.
It winds up looking something like this:
$this->paginate = array (
'Item'=>array(
'conditions'=>array('user_id'=>$id),
'limit' => 6,
'order' => array(
'Item.votes'=>'desc',
'Item.created'=>'desc'
),
'contain'=>array(
'User',
'ItemImage' => array (
'order'=>'ItemImage__imageVotes desc'
)
)
),
'Image'=>array(
'limit'=>6,
'contain'=>array(
'User',
'ItemImage'=>array('Item'),
),
'order'=>array(
'Image.votes'=>'desc',
'Image.views'=>'desc'
),
'conditions'=>array(
'Image.isItemImage'=>1,
'Image.user_id'=>$id
)
)
);
$this->set('items', $this->paginate('Item'));
$this->set('images', $this->paginate('Image'));
That's in the controller. In the view I have sort links that look like this:
<div class="control"><?php echo $this->Paginator->sort('Newest', 'Image.created', array('model'=>'Image')); ?></div>
However, that yields a link that looks like this:
http://localhost/profile/37/page:1/sort:Image.created/direction:asc
There's nothing in there to tell the paginator which model I intend to sort. So when I click on the link it attempts to sort both models by Image.created. The result is an error, because Item cannot be sorted by Image.created. Is there something I'm doing wrong? Or is this something that isn't supported by CakePHP's paginator?
You'll need to override the paginate method for the Model of the Controller of that page.
I did something similar, maybe this snippet will help:
function paginate($conditions, $fields, $order, $limit, $page = 1, $recursive = null, $extra = array())
{
$pageParams = compact('conditions', 'fields', 'order', 'limit', 'page', 'recursive', 'group');
$this->contain('ModuleType', 'NodeDescriptor');
$pageItems = $this->find('all',$pageParams);
$pagesOut = array();
foreach($pageItems as $pageItem)
{
$status = $pageItem['SiteAdmin']['status_id'];
$moduleInfo = null;
$nodeTitle = $pageItem['NodeDescriptor']['title'];
$published = $pageItem['NodeDescriptor']['published'];
$pageitemID = $pageItem['SiteAdmin']['id'];
$moduleId = $pageItem['SiteAdmin']['module_id'];
$contName = $pageItem['ModuleType']['controller'];
if($moduleId)
{
$thisModel = ClassRegistry::getObject($moduleType);
$thisModel->contain();
$moduleInfo = $thisModel->read(null,$moduleId);
$moduleInfo = $moduleInfo[$moduleType];
}
$pagesOut[] = array(
'status'=>$status,
'node'=>$nodeTitle,
'published'=>$published,
'info'=>$moduleInfo,
'module_id'=>$moduleId,
'contName'=>$contName,
'pageitem_id'=>$pageitemID);
}
return $pagesOut;
}
By doing it this way, you gain control over the parameters passed to paginate, so you can pass model specific data, control flags etc.
The easiest solution would be to implement both grids as elements that fetch their own data and use AJAX to load the elements into the page.
The only other option would be to modify the params so you pass the params for both grids to each grid when sorting or stepping through pages. The code posted by Leo above is a good start. You can prepend the Model key from the paginate array onto each named param and make sure you pass all url params to the paginate function and you should be headed in the right direction.