cakephp pagination change urls to make them more seo friendly - php

I am using this syntax:
<ul>
<?php echo $this->Paginator->prev($this->Html->image('arrow_left.png', array('border' => 0, 'tag'=>'li')), array('escape'=>false, 'tag'=>'li')); ?>
<?php echo $this->Paginator->numbers(array('separator' => '', 'tag'=>'li')); ?>
<?php echo $this->Paginator->next($this->Html->image('arrow_right.png', array('border' => 0, 'tag'=>'li')), array('escape'=>false, 'tag'=>'li')); ?>
</ul>
which creates me links like
<li>
4
Is there any way, that I can get rid of the controller and action in the url and use instead the url parameter?
I mean instead of getting links like
http://domain.com/mycontrollername/search/cat:1/page:2?url=slugged_url
I would like to get something like
http://domain.com/slugged_url/cat:1/page:2
Is that possible?
If yes, how?
I have the same issue with results per page:
<?php
$sortDir = ($this->Paginator->sortDir() == 'asc') ? $this->Paginator->sortDir(): 'desc';
$text = ($sortDir == 'asc')? __('aufsteigend', true):__('absteigend', true);
echo $this->Paginator->sort('OBJ_PREIS', $text, $options = array('escape' => false, 'direction'=>'DESC', 'class' => 'asc'))`;
?>
Can I change the urls there as well?
Please advice!
Thanks!!

This is possible using routes. A route will rewrite the URL to something "pretty".
Check the offical CakePHP book. It has a complete chapter just about routing.
The book as plenty of examples for different things you can do with routes as well.

Related

Access id of paginator in controller

Hello guys I am new to Zendframework2.
I have the following line in view\partial\paginator.phtml
<a href="<?php echo $this->url($this->route);?>?page=<?php echo $page; ?>?id=<?php echo $this->id?>">
In browser it looks like http://new_project.localhost/districts?page=2?id=4
new_project is the name of my project, districts is route of controller and
in id=4, 4 is id which I want to access in controller.
I tried:
$_GET['id'];
$this->params()->fromRoute('id'); //also
$this->params()->fromQuery('id'); //also
But non of these works.
How I will access this id in controller?
I solve it, just by putting condition like below:
if (isset($_GET['id']))
{
// perform operation here.
}
Don't build your A element tag href yourself but use the framework like you should.
Url view helper:
// $this->url($routeName, $routeParams, $options, $reuseMatchedParams = false)
$this->url('my/route', ['id' => $object->getId()], ['query' => ['page' => $page]])
Controller plugin:
$this->params('id') // will take ID either from routeParameters or queryParameters.
$this->params()->fromRoute('id') // will take the id from the routeParameters
$this->params()->fromQuery('page') // will take the page from the route query
So when you've got a route with a routeParameter id but your query also has the id within it's query its best practice to keep on using the $this->params()->fromRoute('id') or $this->params()->fromQuery('id') so you always know where the value comes from instead of using $this->params('id').
As with the params plugin you can also define default values on the second argument, like: $this->params()->fromQuery('page', 1). So page will always be 1 if the user did not provide one. The default of the second argument is null. Hope this helps and makes you stop using $_GET['bla']
I think your url should look like this:
http://new_project.localhost/districts?page=2&id=4
^
not ?
Because of the mistake you made the parser probably doesn't parse the id in your url correctly meaning you cannot access it like you tried.
It would be better to use the url view helper for rendering the query parameters in the url then you wouldn't make such a mistake. You can check this post on StackOverflow for reference on how to add query parameters to a url using the url view helper. In your case it would look something like this:
<?php
$href = $this->url($this->route, [], ['query' => [
'page' => $page,
'id' => $id,
]]);
?>
<a href="<?php echo $href ?>">
Now you get the correct url:
http://new_project.localhost/districts?page=2&id=4
Meaning the parser also manages to parse the id correctly.
You should be able to access it now like you tried with:
$this->params()->fromQuery('id'); //returns your id from the url

CakePHP: Bad format URLs

I'm trying to create a simple form in CakePHP detached from a model, I'm having problems with the generated URL:
I get this: (doesn't work -> paypal lowercase)
http://local.dev/integration-cloud/public_html/paypal/checkout
Instead of this: (works -> Paypal camel case)
http://local.dev/integration-cloud/public_html/Paypal/checkout
This is my code:
Paypal/view.ctp
<?php echo $this->Form->create(false, array('action' => 'checkout')); ?>
<?php echo $this->Form->end('Finish'); ?>
UPDATE:
If I try this:
<?php echo $this->Form->create(false, array('url' => array('controller' => 'Paypal', 'action' => 'checkout'))); ?>
<?php echo $this->Form->end('Finish'); ?>
It's work, but I don't want to write on all my views the reference's controller, is there another way to do this?
btw I'm on a Linux server, could be a case sensitive problem?
Thanks,
cakephp conventions want controller name in url to be lowercase and underscored
http://book.cakephp.org/2.0/en/getting-started/cakephp-conventions.html#url-considerations-for-controller-names
It works even with uppercase controller names but you have to set it manually in every form
You can do as below if you want:
<?php echo $this->Form->create(false, array('url' => '/Paypal/checkout')); ?>
<?php echo $this->Form->end('Finish'); ?>
But the below one is recommended in CakePHP:
<?php echo $this->Form->create(false, array('url' => array('controller' => 'Paypal', 'action' => 'checkout'))); ?>
<?php echo $this->Form->end('Finish'); ?>
The problem here was a mix up between the Paypal's plugin and the name of my controller PaypalController.
public $name = 'Paypal';
When I call paypal (lowercase) CakePHP is trying to call the plugin instead my PaypalController class.
http://local.dev/integration-cloud/public_html/paypal/checkout
So to fix this problem I had to change the name of my controller to PaypalPaymentProcessor

Routing a subdomain in CakePHP with HTML-Helper

I have a mobile page running on a subdomain "m.mydomain.com". This is all working fine, but I would like to remove the controller in the URL when using the subdomain.
m.mydomain.com/mobiles/tips
should become
m.mydomain.com/tips
by using the HTML-Helper.
At the moment a link looks like that:
$html->link('MyLink', array('controller' => 'mobiles', 'action'=> 'tips'));
I tried several possible solutions with the routes and also some hacks in the bootstrap but it did not work out for me.
In the CakeBakery I found this but that does not solve my issue.
Does anyone have an idea for this issue?
Gathering code from the page you mentioned:
Constraint: you cannot have a controller called tips or foo in this setup
In /config/routes.php:
$subdomain = substr( env("HTTP_HOST"), 0, strpos(env("HTTP_HOST"), ".") );
if( strlen($subdomain)>0 && $subdomain != "m" ) {
Router::connect('/tips',array('controller'=>'mobiles','action'=>'tips'));
Router::connect('/foo', array('controller'=>'mobiles','action'=>'foo'));
Configure::write('Site.type', 'mobile');
}
/* The following is available via default routes '/{:controller}/{:action}'*/
// Router::connect('/mobiles/tips',
// array('controller' => 'mobiles', 'action'=>'tips'));
// Router::connect('/mobiles/foo',
// array('controller' => 'mobiles', 'action'=>'foo'));
In your Controller action:
$site_is_mobile = Configure::read('Site.type') ?: '';
Then in your view:
<?php
if ( $site_is_mobile ) {
// $html will take care of the 'm.example.com' part
$html->link('Cool Tips', '/tips');
$html->link('Hot Foo', '/foo');
} else {
// $html will just output 'www.example.com' in this case
$html->link('Cool Tips', '/mobiles/tips');
$html->link('Hot Foo', '/mobiles/foo');
}
?>
This will allow you to output the right links in your views (in a bit I'll show you how to write even less code) but the $html helper will not be able -- by no amount of magic -- to use controller-action routes to another domain. Be aware that m.example.com and www.example.com are different domains as far as the $html helper is concerned.
Now, if you want you can do the following in your controller to take some logic off your view:
<?php
$site_is_mobile = Configure::read('Site.type') ?: '';
if ( $site_is_mobile !== '' ) {
$tips_url = '/tips';
$foo_url = '/foo';
} else {
$tips_url = '/mobile/tips';
$foo_url = '/mobile/foo';
}
// make "urls" available to the View
$this->set($tips_url);
$this->set($foo_url);
?>
And in your view you don't need to worry about checking whether the site is being accessed via m.example.com/tips or www.example.com/mobile/tips:
<?php echo $html->link("Get some kewl tips", $tips_url); ?>
For more advanced routing in CakePHP-1.3 refer to Mark Story's article on custom Route classes
Let us know ;)

CakePHP Routing help

I want to make my /pages/about become just `/about
I tried doing it with the routing in routes.php but couldn't get it working e.g. Router::connect('/pages/about', array('controller' => 'pages', 'action' => 'display'));
can anyone help?
ALSO
for my portfolio controller I have it currently showing work like /portfolio/view/102 but I would like to display it something like /portfolio/view/Paperview_Magazine-102 where Paperview Magazine is the title of the post and 102 is the ID of the post. I have looked at the Cake Book but if someone could post up some code that'd be awesome.
Thanks
To make a route for /about, you need to make a route for /about, not /pages/about:
Router::connect('/about',
array('controller' => 'pages', 'action' => 'display', 'about'));
To use URLs like /portfolio/view/Paperview_Magazine-102, you can use standard routes, but you'll have to do a little work in the controller:
// PortfolioController
// $identifier == "Paperview_Magazine-102"
public function view($identifier) {
if (!preg_match('/^(.+)-(\d+)$/', $identifier, $matches)) {
// $identifier is not in format 'Title-Id'
$this->cakeError('error404');
}
// $matches[1] == Paperview_Magazine
// $matches[2] == 102
$post = $this->Portfolio->read(null, $matches[2]);
$this->set(compact('post'));
}
Maybe a bit of a long shot, but in the first one you could try Router::connect('/:controller/about', array('action'=>'display'));? I seem to remember having some similar problems with my routes and this maybe helping, though I can't remember why.
With the second question, can't you just rework the view function so it accepts a $slug parameter instead of $id, and find the right portfolio record by searching on the slug instead? Or check if the parameter is_numeric, and search for an id if it is, or a slug if it isn't...

change CakePhp1.3 paginator destination url?

I'm new to cakephp...and I have a page with a url this:
http://localhost/books/filteredByAuthor/John-Doe
so the controller is ´books´, the action is ´filteredByAuthor´ and ´John-Doe´ is a parameter.. but the url looks ugly so i've added a Route like this:
Router::connect('/author/:name', array( 'controller' => 'books','action' => 'filteredByAuthor'), array('pass'=>array('name'),'name'=>".*"));
and now my link is:
http://localhost/author/John-Doe
the problem is that the view has a paginator and when i change the page (by clicking on the next or prev button).. the paginator won't consider my routing... and will change the url to this
http://localhost/books/filteredByAuthor/John-Doe/page:2
the code on my view is just:
<?php echo $this->Paginator->prev('<< ' . __('previous', true), array(), null, array('class'=>'disabled'));?>
the documentation doesn't say anything about avoiding this and i've spent hours reading the paginators source code and api.. and in the end i just want my links to be something like this: (with the sort and direction included on the url)
http://localhost/author/John-Doe/1/name/asc
Is it possible to do that and how?
hate to answer my own question... but this might save some time to another developper =) (is all about getting good karma)
i found out that you can pass an "options" array to the paginator, and inside that array you can specify the url (an array of: controller, action and parameters) that the paginator will use to create the links.. so you have to write all the possible routes in the routes.php file. Basically there are 3 possibilities:
when the "page" is not defined
For example:
http://localhost/author/John-Doe
the paginator will assume that the it's the first page. The corresponding route would be:
Router::connect('/author/:name', array( 'controller' => 'books','action' => 'filteredByAuthor'),array('pass'=>array('name'),'name'=>'[a-zA-Z\-]+'));
when the "page" is defined
For example:
http://localhost/author/John-Doe/3 (page 3)
The route would be:
Router::connect('/author/:name/:page', array( 'controller' => 'books','action' => 'filteredByAuthor'),array('pass'=>array('name','page'),'name'=>'[a-zA-Z\-]+','page'=>'[0-9]+'));
finally when the page and the sort is defined on the url (by clicking on the sort links created by the paginator).
For example:
http://localhost/author/John-Doe/3/title/desc (John Doe's books ordered desc by title)
The route is:
Router::connect('/author/:name/:page/:sort/:direction', array( 'controller' => 'books','action' => 'filteredByAuthor'),
array('pass'=>array('name','page','sort','direction'),
'name'=>"[a-zA-Z\-]+",
'page'=>'[0-9]*',
'sort'=>'[a-zA-Z\.]+',
'direction'=>'[a-z]+',
));
on the view you have to unset the url created by the paginator, cause you'll specify your own url array on the controller:
Controller:
function filteredByAuthor($name = null,$page = null , $sort = null , $direction = null){
$option_url = array('controller'=>'books','action'=>'filteredByAuthor','name'=>$name);
if($sort){
$this->passedArgs['sort'] = $sort;
$options_url['sort'] = $sort;
}
if($direction){
$this->passedArgs['direction'] = $direction;
$options_url['direction'] = $direction;
}
Send the variable $options_url to the view using set()... so in the view you'll need to do this:
View:
unset($this->Paginator->options['url']);
echo $this->Paginator->prev(__('« Précédente', true), array('url'=>$options_url), null, array('class'=>'disabled'));
echo $this->Paginator->numbers(array('separator'=>'','url'=>$options_url));
echo $this->Paginator->next(__('Suivante »', true), array('url'=>$options_url), null, array('class' => 'disabled'));
Now, on the sort links you'll need to unset the variables 'sort' and 'direction'. We already used them to create the links on the paginator, but if we dont delete them, then the sort() function will use them... and we wont be able to sort =)
$options_sort = $options_url;
unset($options_sort['direction']);
unset($options_sort['sort']);
echo $this->Paginator->sort('Produit <span> </span>', 'title',array('escape'=>false,'url'=>$options_sort));
hope this helps =)

Categories