CAKEPHP paginator custom link - cakephp

I want an custom link for my paginator. I use the folowing code
$this->Paginator->options(array(
'url'=>array(
"/custom",24,"custom1"
),
'escape'=>false
)
);
This results in a link with the original controller in front of the link like this:
/controller/action/%2Fcustom/24/custom1
I want the linkt to be /custom/24/custom1. So without the escaped(/) and as a root.
How can I accomplish this?

Did you try
'url' => '/custom/24/custom1'
? The syntax that you use is not valid I think. The available formats are:
'url' => 'action'
or
'url' => '/controller/action'
or
'url' => array(
'controller' => 'your_controller',
'action' => 'your_action'
)
See http://book.cakephp.org/1.3/en/view/1387/options-url and http://book.cakephp.org/1.3/view/1448/url.
If none of these formats satisfies you, you can consider creating a custom route, see http://book.cakephp.org/1.3/view/948/Defining-Routes.
Cheers

Related

How to redefine the URLs generation without changes at the HtmlHelper#link(...) calls in CakePHP?

I have a CakePHP website with many internal links, that are build with the HtmlHelper:
/app/View/MyController/myaction.ctp
<?php
echo $this->Html->link(
$item['Search']['name'],
array(
'controller' => 'targetcontroller',
'action' => 'targetaction',
$profileId,
$languageId
)
);
?>
It works fine with the default route:
/app/Config/routes.php
Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
The generated links look like that: /mycontroller/myaction/$profileId/$languageId.
Now I want to use search engine friendly URLs (with profile names and ISO-639-1 language codes instead of IDs) for a part of the website and added a new Route:
/app/Config/routes.php
Router::connect(
'/:iso6391/:name.html',
array('controller' => 'mycontroller', 'action' => 'myaction'),
array(
'iso6391' => '[a-zA-Z]+',
'name' => '[0-9a-zA-ZäöüßÄÖÜ\-]+',
)
);
And it also works fine and the incomming URIs like /producer/en/TestName.html are interpreted correctly.
But the HtmlHelper is still generating the old URIs like /mycontroller/myaction/1/1.
The docu says:
Reverse routing is a feature in CakePHP that is used to allow you to easily change your URL structure without having to modify all your code. By using routing arrays to define your URLs, you can later configure routes and the generated URLs will automatically update.
Well, the HtmlHelper gets a routing array as input, that means: I'm using the reverse routing.
Why does it not work? How to make the HtmlHelper generate the new URLs (without changing the HtmlHelper#link(...) calls)?
Bit of explanation first
You are technically not using reverse routing. You see, the output link, /mycontroller/myaction/1/1 definitively doesn't match /iso/name.html. Like, in no way. So, the routing skips that rule because it doesn't apply.
Code
Try this
echo $this->Html->link(
$item['Search']['name'],
array(
'controller' => 'targetcontroller',
'action' => 'targetaction',
'iso6391' => $someStringWithIso,
'name' => $someName
)
);
But for that, you have to change your routing a bit, because you are not passing the parameters (check the docs for examples)
Router::connect(
'/:iso6391/:name.html',
array('controller' => 'mycontroller', 'action' => 'myaction'),
array(
'pass' => array('iso6391', 'name'),
'iso6391' => '[a-zA-Z]+',
'name' => '[0-9a-zA-ZäöüßÄÖÜ\-]+',
)
);
And you have to mind the first string match /:iso6391/:name.html. Do you want to match this route to every controller and action in your project, or just the one controller and the one view. If it is for all projects, just for precaution, use this
/:controller/:action/:iso6391/:name.html
if is just for, say, Controller1 and action "view", use
/controller1/view/:iso6391/:name.html
The detail you need to consider is the extension you use .html, is that really necessary in the url? If it is, add it as a parameter in the Html#link
echo $this->Html->link(
$item['Search']['name'],
array(
'controller' => 'targetcontroller',
'action' => 'targetaction',
'iso6391' => $someStringWithIso,
'name' => $someName
'ext' => 'html'
)
);
and also add parseExtensions to the routing file. Read this. Would be easier if you don't add the extension, but that's up to you.
In the end, you still have to change your calls to Html->link...

want to remove action name from url CakePHP

i am working on a Cakephp 2.x.. i want to remove the action or controller name from url ... for example i am facing a problem is like that
i have a function name index on my Messages controller in which all the mobile numbers are displaying
the url is
www.myweb.com/Messages
now in my controller there is a second function whose name is messages in which i am getting the messages against the mobile number
so now my url becomes after clicking the number is
www.myweb.com/Messages/messages/823214
now i want to remove the action name messages because it looks weired...
want to have a url like this
www.myweb.com/Messages/823214
When connecting routes using Route elements you may want to have routed elements be passed arguments instead. By using the 3rd argument of Router::connect() you can define which route elements should also be made available as passed arguments:
// SomeController.php
public function messages($phoneNumber = null) {
// some code here...
}
// routes.php
Router::connect(
'/messages/:id', // E.g. /messages/number
array('controller' => 'messages', 'action' => 'messages'),
array(
// order matters since this will simply map ":id"
'id' => '[0-9]+'
)
);
and you can also refer link above given by me, hope it will work for you.
let me know if i can help you more.
REST Routing
The example in the question looks similar to REST routing, a built in feature which would map:
GET /recipes/123 RecipesController::view(123)
To enable rest routing just use Router::mapResources('controllername');
Individual route
If you want only to write a route for the one case in the question
it's necessary to use a star route:
Router::connect('/messages/*',
array(
'controller' => 'messages',
'action' => 'messages'
)
);
Usage:
echo Router::url(array(
'controller' => 'messages',
'action' => 'messages',
823214
));
// /messages/823214
This has drawbacks because it's not possible with this kind of route to validate what comes after /messages/. To avoid that requires using route parameters.
Router::connect('/messages/:id',
array(
'controller' => 'messages',
'action' => 'messages'
),
array(
'id' => '\d+',
)
);
Usage:
echo Router::url(array(
'controller' => 'messages',
'action' => 'messages',
'id' => 823214 // <- different usage
));
// /messages/823214
in config/routes.php
$routes->connect('/NAME-YOU-WANT/:id',
['controller' => 'CONTROLLER-NAME','action'=>'ACTIOn-NAME'])->setPass(['id'])->setPatterns(['id' => '[0-9]+']
);
You can use Cake-PHP's Routing Features. Check out this page.

Routing with named parameters

I have a URL that contains named parameters, which I want to map to a more user friendly URL.
Take, for example, the following URL:
/videos/index/sort:published/direction:desc
I want to map this to a more friendly URL, like:
/videos/recent
I have tried setting it up in the Router, but it doesn't work.
Code samples from the Router:
Router::connect(
'/videos/recent/*',
array('controller' => 'videos', 'action' => 'index'),
array('sort' => 'published', 'direction' => 'desc'
));
Which doesn't work. And the following also doesn't work:
Router::connect(
'/videos/recent/*',
array('controller' => 'videos', 'action' => 'index', 'sort' => 'published', 'direction' => 'desc'));
Any ideas?
Use get args
The easiest way to have routes work is to avoid named arguments all together. With pagination thats easy to achieve using appropriate config:
class FoosController extends AppController {
public $components = array(
'Paginator' => array(
'paramType' => 'querystring'
)
);
}
In this way when you load /videos/recent you should find it includes urls of the form:
/videos/recent?page=2
/videos/recent?page=3
Instead of (due to route mismatching)
/videos/index/sort:published/direction:desc/page:2
/videos/index/sort:published/direction:desc/page:3
But if you really want to use named args
You'll need to update your route definition - there's no page in the route config:
Router::connect(
'/videos/recent/*',
array(
'controller' => 'videos',
'action' => 'index',
'sort' => 'published',
'direction' => 'desc'
)
);
As such, if there is a page named parameter (which there will be for all urls generated by the paginator helper), the route won't match. You should be able to fix that by adding page to the route definition:
Router::connect(
'/videos/recent/*',
array(
'controller' => 'videos',
'action' => 'index',
'sort' => 'published',
'direction' => 'desc',
'page' => 1
)
);
Though even if it works, you may find it to be fragile.
lets see on [Router::connect documentation](Routes are a way of connecting request urls to objects in your application)
Routes are a way of connecting request urls to objects in your application
So, it's map urls to objects and not url to url.
You have 2 options:
use Router::redirect
Something like that:
Router::redirect( '/videos/recent/*', '/videos/index/sort:published/direction:desc');
but seems that's not that you want exactly
use Router::connect
use normal Router::connect which will connect url to some action which make appropriate scope. Something like that:
Router::connect(
'/videos/recent/*',
array(
'controller' => 'videos',
'action' => 'recent'
)
);
and in VideosController
public function recent() {
$this->request->named['sort'] = 'published';
$this->request->named['direction'] = 'desc';
$this->index();
}
it works and I saw such usage, but not sure, that is will satisfy you too.
as for me, I like normal named cakephp parameters. If such scope (published and desc) is your default state, just code default state in index action. For over cases i think it's normal to use ordinary named parameters.

CakePHP 1.3: Use Route to get the following URL format /news/06/27/12/slug-slug-slug

All,
I currently have slug setup in my app where I generate the following as links:
http://www.domain.com/article/my-first-news-article.
And this is the current route that I use to accomplish that in addition to the view acepting a slug instead of id:
Router::connect('/article/*',array('controller' => 'articles', 'action' => 'view'));
However, I wanted to improve that a little bit more by adding published date to the URL like the following:
http://www.domain.com/article/2012/06/27/my-first-news-article
I have the following code from the CakePHP manual, but it doesnt seem to work:
Router::connect(
'/article/:year/:month/:day/:slug',
array(
'controller' => 'articles',
'action' => 'view'
),
array(
'year' => '[12][0-9]{3}',
'month' => '0[1-9]|1[012]',
'day' => '0[1-9]|[12][0-9]|3[01]'
)
);
For the sake of this, I really dont care what date is passed to the view. I just care about the slug that is passed. Then I will use function view($slug) to find the article and display it. However the URL needs to be http://www.domain.com/2012/06/27/slug-slug-slug
Thank you....
How do the $this->Html->link() calls look like in the places where you want to use the date in the link?
Are you adding the required params there?
$this->Html->link('Article', array('year' => 2012, 'month' => 01, 'day' => 01, 'action' => 'view', 'slug' => $article['Article']['slug']));
For the sake of completeness, and because somebody else might be interested in this as well, I'll show you my solution to a similar problem:
I want to have URLS in the format
http://mydomain.com/blog/2012/06/slug-slug-slug
i.e. /blog/yyyy/mm/slug
For this, I use
// view a post by year and month and title
Router::connect('/blog/:year/:month/:title/*', array(
'controller' => 'posts',
'action' => 'view'
), array(
'year' => '[12][0-9]{3}',
'month' => '0[1-9]|1[012]',
'title' => '[a-z0-9-]+'
));
With the rules below, you can make sure the correct formats are entered. It also prevents users from entering values such as &"% as slugs.
The /* after title even allows for additional parameters, e.g. for pagination, when your blog entry has several pages (http://mydomain.com/blog/2012/06/slug/page:2).
I also realized that setting the "pass" array is not really necessary (at least in CakePHP 2.0). You can access the parameters directly via $this -> request -> params['year'], etc.
After more research and trials I was able to figure it out.
The following route will work to accept a URL like this:
http://www.mydomain.com/article/2009/06/10/my-first-article-in-mydomain-dot-com.
As a matter of fact, it doesnt actually matter how the date is setup and it will still work. It could also be,
http://www.mydomain.com/article/06/10/2012/my-first-article-in-mydomain-dot-com
Router::connect(
'/article/:year/:month/:day/:slug',
array(
'controller' => 'articles',
'action' => 'view'
),
array(
'pass' => array('slug')
)
);

how to change part of url from cakephp's paginator options?

have custom pagination in my cakephp view. before that i made some custom routing changes.
problem is that links leads to pages like
http://localhost/myapp/foos/view/news/page:2
instead of
http://localhost/myapp/news/page:2
so, part with foos/view/ not have to be part of the link.
tried to change url with several custom options, like
$this->Paginator->options(array('url' => $this->passedArgs));
but no luck, because i always have foos/view/ in url.
can you help me how can i get rid of that foos/view?
thank you very much in advance!
UPDATE: i manage to do "something", but not enough, by adding following lines:
$options = array('url'=> array('controller' => 'news' ) );
$paginator->options($options);
now, my link looks like:
http://localhost/myapp/news/index/page:2
how can i get rid of that "index" in url?
The following line is more about passing various pieces of URL information to the view:
$this->Paginator->options(array('url' => $this->passedArgs));
I think what you want to look into is the helper declaration in your Controller:
var $helpers = (
'SomeHelper',
'AnotherHelper',
'Paginator' => array(
'url' => array('controller'=>'news')
)
);
If you want finer control of a custom route like the one you have then try
'url' => '/news'
I haven't used PaginatorHelper in a while - so I could be egregiously on the wrong track - but I believe that's a good start.
Also, take a look at the Paginator Helper page for where it mentions $options and then take a look at Router::url() as the former page recommends.
I had a case where I am working on a project using CakePHP 2.1 (This thread is tagged as 1.3) with a dynamic admin route to display pages like this:
Router::connect('/admin/main/*', array('controller' => 'adminPages', 'action' => 'display'));
With a query string parameter, that produces a dynamic url like this: http://mydomain.com/adminPages/main/...?page=1
The link route, was incorrect for our needs and found I could alter the url directly by using this:
$this->Paginator->options(array(
'url' => array(
'controller' => 'admin/main/my-display',
)
));
For me it made a link: http://mydomain.com/admin/main/my-display?page=1 - which was the correct url we were looking for. If I used a string, as described above, it appends itself to the url, like: http://mydomain.com/adminPages/main/.../admin/main/my-display?page=1
In view :
<?php
$this->Paginator->options(array('url' => array('controller' => '','action' =>'your-custom-url')));
?>
In routes.php :
<?php
Router::connect('/your-custom-url/*', array('controller' => 'Controller', 'action' => 'function'));
?>

Resources