I have an action called index and another one called manage, both in PostsController. I want to implement pagination for both, and I've set up this class attribute:
public $paginate = array(
'limit' => 10,
'order' => array(
'Post.created' => 'desc'
)
);
then I'm using the pagination in my index action like so: $this->set('posts', $this->paginate('Post'));
This results in a URL like so: http://dev/posts/page:2 which is fine.
However, when I try to use pagination in my manage action just like I did with index ($this->set('posts', $this->paginate('Post'));), the pagination links on my view redirect to the URL above, rather than the manage action.
Basically, Cake is getting confused because I'm using pagination twice in the same controller and it's redirecting both to the same URL. How can I make sure that the pagination for the manage action works properly?
Do the followings.
<?php
class PostsController extends AppController
{
var $name = 'Posts';
public $paginate = array
(
'limit' => 10,
'order' => array
(
'Post.created' => 'desc'
)
);
function index()
{
$this->Post->recursive = 0;
$this->set('posts', $this->paginate('Post'));
}
function manage()
{
$this->Post->recursive = 0;
$this->set('posts', $this->paginate('Post'));
}
}
make changes in view file as defined below.
index.ctp
$options = array
(
'url'=> array
(
'controller' => 'posts',
'action' => 'index'
)
);
$paginator->options($options);
manage.ctp
$options = array
(
'url'=> array
(
'controller' => 'posts',
'action' => 'manage'
)
);
$paginator->options($options);
And you are done.
Related
I have one web page and in this page I need total 2 paginations for different different 2 tables.
I have tried with different pagination but it's dependent with each other.
For ex., If I select second page of first table then second table automatically changed with 2nd page.
Here is my controller code code :
$page = $this->pageForPagination('User');
$this->paginate = array(
'User' => array(
'fields' => array(
'User.*',
),
'conditions' => $userConditions,
'page' => $page,
),
);
$this->set('users', $this->paginate('User'));
$page1 = $this->pageForPagination('Game');
$this->paginate = array(
'Game' => array(
'fields' => array(
'Game.*',
),
'conditions' => $conditions,
'page' => $page1,
),
);
$this->set('games', $this->paginate('Game'));
Here is the function that is used in above code :
function pageForPagination($model) {
$page = 1;
$sameModel = isset($this->params['named']['model']) && $this->params['named']['model'] == $model;
$pageInUrl = isset($this->params['named']['page']);
if ($sameModel && $pageInUrl) {
$page = $this->params['named']['page'];
}
$this->passedArgs['page'] = $page;
return $page;
}
Here is my view code :
echo $this->element('paging', array('model' => 'User'));
echo $this->element('paging', array('model' => 'Game'));
I have referred above code from this url : http://debuggable.com/posts/how-to-have-multiple-paginated-widgets-on-the-same-page-with-cakephp:48ad241e-b018-4532-a748-0ec74834cda3
Can any one help me because I didn't get any solution still?
The solution in the link you mentioned is to override the default pagination urls and doesn't display both models at the same time. You haven't implemented the solution completely.
You have to extract the page number manually for each model like this:
function pageForPagination($model) {
if (isset($this->params['named']['pagefor'.$model])
return $this->params['named']['pagefor'.$model];
else
return 1;
}
The code below:
echo $this->element('paging', array('model' => 'User'));
echo $this->element('paging', array('model' => 'Game'));
causes the cakephp to use the default pagination view and the urls in the default pagination are the same for both models. You have to use custom pagination view and specify the model for the page link.
For the edited function above you can use a url pattern like this:
/Controller/Action/pageforUser:215/pageforGame:35
for each page link in your view.
I think best practice to use this url pattern is to override the pagination helper so that the links that are created form the following pattern:
'/Controller/Action/pagefor[Model]:215'.[other parameters]
I'm using CakePHP v2.4.1, and I'm trying to have two separate models be paginated on the same page, through the same controller action (index)
I want to have a NewsPost paginated on a single page, and the EventPost also paginated separately on the same page. Is this bad practice, or is it possible to set conditions to change the $this->paginate variable to paginate properly depending on which model it is on?
My Controller looks like this:
public $uses = array(
'NewsPost',
'NewsPostComment',
'EventPost',
'EventPostComment'
);
public $paginate = array(
'limit' => 9,
'order' => array(
'NewsPost.created' => 'desc'
),
'recursive' => 1,
);
public function index() {
$this->paginate = array(
'limit' => 1,
'order' => array(
'EventPost.created' => 'desc'
),
'recursive' => 1,
);
$this->Paginator->settings = $this->paginate;
$newsPosts = $this->paginate('NewsPost');
$eventPosts = $this->EventPost->find('all');
$this->set(array('newsPosts' => $newsPosts, 'eventPosts' => $eventPosts));
The built-in cake paginator does not seem to allow for the options of paginating separate models, or am I wrong?
Here is the view for pagination:
<?php
$params = $this->Paginator->params();
if ($params['count'] > 0): ?>
<div class="pagination-totals pull-left">
<?php echo $this->Paginator->counter(array('format' => __('{:start} to {:end} of {:count}'))) ?>
</div>
<?php endif; ?>
<?php echo $this->Paginator->numbers(array(
'class' => 'pull-right',
'prev' => '<',
'next' => '>',
));
?>
The problem is, when I choose page two for the NewsPost, it switches to page two for the EventPost, so how can I differentiate between both separate models on the same page using CakePHP pagination?
Thanks
You have just one params named page in your page so the result in normal.
You have to handle this with ajax request and separated actions
I want to make my url seo friendly. www.example.com/posts/view/1 change for www.example.pl/:slug-:id. Everything works fine, but probably I'm doing something wrong with routing, because when after clicking the urls in paginator, the url is correct, it looks like www.example.pl/:slug-:id , but it appears an error
"The requested address 'www.example.pl/:slug-:id' was not found on this server."
I don't know what's wrong. Here's my code:
Router::connect(
'/:slug-:id',
array(
'controller' => 'posts',
'action' => 'view'
),
array(
'pass' => array('slug' , 'id'),
'id' => '[0-9]+'
)
);
in paginator view:
echo $this->Html->link($ad['Post']['title'], array(
'controller' => 'posts',
'action' => 'view',
'slug' => Inflector::slug($post['Post']['title'],'-'),
'id'=>$post['Post']['id'])
);
I solved the problem.
Its too simple i'll give you an example from my project ..
in your routes.php
Router::connect(
'/:slug-:id',
array('controller'=>'posts','action'=>'view'),
array('pass'=>array('slug','id'),'slug'=>'[a-zA-Z0-9 -]+','id'=>'[0-9]+')
);
your link in views should be like .
$this->Html->link(__('link desu'),array('controller'=>'posts','action'=>'view','id'=>$post['Post']['id'],'slug'=>$post['Post']['slug']));
and your PostsController.php
public function view($slug,$id){
$this->Post->id = $id;
// ....
}
Quick tip : try to create an array in your PostModel to avoid creating it every time in your view .
example :
Post.php
class Post extends AppModel{
// ....
public function afterFind($results,$primary = false){
foreach ($results as $key => $value) {
if(isset($value[$this->alias]['id'])){
$results[$key][$this->alias]['url'] = array(
'controller'=>'posts',
'action'=>'view',
'id'=>$results[$key][$this->alias]['id'],
'slug'=>$results[$key][$this->alias]['slug']
);
}
// ....
}
return $results;
}
}
}
so you can call it in your view simply like that
$this->Html->link(__('link desu'),$post['Post']['url']);
It's probably a problem with the regex on the route. Your slug contain hyphens - which you also use to separate between the slug and the id. i.e.:
example.com/my-slug-has-hyphens-1
The regex is not smart enough to know that the "last" hyphen separates the slug from the id.
To test if this is the problem, try using a route like this '/:slug__:id', just to see if it works.
I solved the problem. In the posts controller my view function was wrong. Here's right correct:
function view($id = null, $slug = null) {
$this->Post->id = $this->params['post'];
$this->set('post', $this->Post->read());
Pass is order sensitive
In the question the route is as follows:
Router::connect(
'/:slug-:id',
array(
'controller' => 'posts',
'action' => 'view'
),
array(
'pass' => array('slug' , 'id'), # <-
'id' => '[0-9]+'
)
);
That means the post function will recieve:
public function view($slug, $id)
As indicated by the edited question, the code is expecting the id to be the first parameter. The easiest solution is simply to specify the passed parameters in the order that they are expected:
...
'pass' => array('id', 'slug'), # <-
Router::connect(
'/:slug/:id',
array(
'controller' => 'posts',
'action' => 'view'
),
array(
'pass' => array('slug' , 'id'),
'id' => '[0-9]+'
)
);
the above code will create correct link as www.example.com/posts/view/title/1
echo $this->Html->link($post['Post']['title'], array('controller' => 'posts', 'action' => 'view', Inflector::slug($post['Post']['title'],'-'),$post['Post']['id']));
I've just baked a simple CakePHP app, and I'm trying to customize how records are paginated. I have this action in my controller:
public function index() {
$this->Recipe->recursive = 0;
$this->set('recipes', $this->Recipe->paginate());
}
This works fine with the default pagination. I'm trying to customize the amount of rows returned and their order by using a class property called $paginate in the same controller:
public $paginate = array(
'limit' => 1,
'order' => array(
'Recipe.title' => 'asc'
)
);
However it's taking no effect at all. The results still have the default limit and sort order. I've also tried setting up $this->paginate in my action, however this seems to get ignored also:
public function index() {
$this->paginate = array(
'limit' => 1,
'order' => array(
'Recipe.title' => 'asc'
)
);
$this->set('recipes', $this->Paginator->paginate());
}
What could be causing Cake to ignore the pagination options I'm setting? Does it perhaps do something funky when you bake the application which I'm not aware of?
Try
public function index() {
$this->Paginator->settings = array(
'limit' => 1,
'order' => array(
'Recipe.title' => 'asc'
)
);
$this->set('recipes', $this->Paginator->paginate());
}
I've got two or more routes that will be going to the same controller and action. This is fine until I want to use a helper such as the form helper or pagination on the page.
What happens is that the current url changes to whatever is declared first in my routes.php file.
I see there is a way to promote a router with Router::promote but I'm not sure if I can do it based on the current url or router being used or if there's a bett way to do this.
Here's an example of what my router.php looks like:
Router::connect('/cars-for-sale/results/*', array('controller' => 'listings', 'action' => 'results'));
Router::connect('/new-cars/results/*', array('controller' => 'listings', 'action' => 'results'));
Router::connect('/used-cars/results/*', array('controller' => 'listings', 'action' => 'results'));
Let's say for example that I'm at the url domain.com/used-cars/results/ and I'm using the form helper or pagination helper, the url that is being put in the action or href is domain.com/cars-for-sale/results/.
Any help or info would be appreciated.
Routes should be unique and identifiable!
The problem with these Routes is that, basically, you created duplicate URLs not only does this cause problems with CakePHP picking the right route, Google doesn't like that as well; duplicated content will have a negative effect on your SEO ranking!
In order to pick the right URL (Route), CakePHP should be able to do so, based on its parameters; your current Routes do not offer any way to distinguish them.
And neither does your application!
All these URLs will present the same data;
/cars-for-sale/results/
/new-cars/results/
/used-cars/results/
Solution 1 - separate actions
If your application is limited to these three categories, the easiest solution is to create three actions, one per category;
Controller:
class ListingsController extends AppController
{
const CATEGORY_NEW = 1;
const CATEGORY_USED = 2;
const CATEGORY_FOR_SALE = 3;
public $uses = array('Car');
public function forSaleCars()
{
$this->set('cars', $this->Paginator->paginate('Car', array('Car.category_id' => self::CATEGORY_FOR_SALE)));
}
public function newCars()
{
$this->set('cars', $this->Paginator->paginate('Car', array('Car.category_id' => self::CATEGORY_NEW)));
}
public function usedCars()
{
$this->set('cars', $this->Paginator->paginate('Car', array('Car.category_id' => self::CATEGORY_USED)));
}
}
Routes.php
Router::connect(
'/cars-for-sale/results/*',
array('controller' => 'listings', 'action' => 'forSaleCars')
);
Router::connect(
'/new-cars/results/*',
array('controller' => 'listings', 'action' => 'newCars')
);
Router::connect(
'/used-cars/results/*',
array('controller' => 'listings', 'action' => 'usedCars')
);
Solution 2 - Pass the 'category' as parameter
If the list of URLs to be used for the 'listings' will not be fixed and will expand, it may be better to pass the 'filter' as a parameter and include that in your routes;
routes.php
Router::connect(
'/:category/results/*',
array(
'controller' => 'listings',
'action' => 'results',
),
array(
// category: lowercase alphanumeric and dashes, but NO leading/trailing dash
'category' => '[a-z0-9]{1}([a-z0-9\-]{2,}[a-z0-9]{1})?',
// Mark category as 'persistent' so that the Html/PaginatorHelper
// will automatically use the current category to generate links
'persist' => array('category'),
// pass the category as parameter for the 'results' action
'pass' => array('category'),
)
);
Read about the Router API
In your controller:
class ListingsController extends AppController
{
public $uses = array('Car');
/**
* Shows results for the specified category
*
* #param string $category
*
* #throws NotFoundException
*/
public function results($category = null)
{
$categoryId = $this->Car->Category->field('id', array('name' => $category));
if (!$categoryId) {
throw new NotFoundException(__('Unknown category'));
}
$this->set('cars', $this->Paginator->paginate('Car', array('Car.category_id' => $categoryId)));
}
}
And, to create a link to a certain category;
$this->Html->link('New Cars',
array(
'controller' => 'listings',
'action' => 'results',
'category' => 'new-cars'
)
);