Is there a function to generate the corresponding URL given the request object?
For example, if the request params values are:
params => array(
'plugin' => 'plugin',
'controller' => 'foo',
'action' => 'bar',
'named' => array(),
'pass' => array()
)
data => array()
query => array(
'key' => 'val'
)
)
Then, generate the URL:
http://domain.com/plugin/foo/bar?key=val
Whether this fits your needs depends of course, but generally Router::reverse() is able to build a URL from a request object:
Router::reverse($cakeRequestObject, true)
It's much like Router::url(), but it will do all the dirty work for you like including the query values and removing unnecessary parameters.
Just Use Router::reverse() like that way :
$url = Router::reverse($this->params);
echo $url;
Related
I created custom url route like this:
Router::connect('/subjects.details', array(
'plugin' => 'subjects',
'controller' => 'subjects',
'action' => 'details'
));
However that action/view needs a parameter.
So when I go to link like localhost/foo/subjects.details/12 it gives me missing controller error.
Missing Controller
Error: Subjects.detailsController could not be found.
Error: Create the class Subjects.detailsController below in file:
app/Controller/Subjects.detailsController.php
How do I add id param for this url?
You have to define the param in the url and in your action as well:
Router::connect('/subjects.details/:id', array(
'plugin' => 'subjects',
'controller' => 'subjects',
'action' => 'details'
));
Lasers answer returned another error. It basically added new key 'id' => '1' into $this->params array instead into $this->params 's 'passed' key array. By changing it into this it works:
Router::connect('/subjects.details/*', array(
'plugin' => 'subjects',
'controller' => 'subjects',
'action' => 'details'
));
Here is a working solution. You have to passed the params and then it'll start working. Here is the way-
Router::connect('/subjects.details/:id', [
'plugin' => 'subjects',
'controller' => 'subjects',
'action' => 'details'
],
[
'pass' => ['id']
]
);
And your method should look like this-
public function details($id){
//....
}
I hope this can be helpful. Thanks.
I'm using CakePHP version 2.2.3 I have an element with a search box and a few dropdowns that use CakeDC's search plugin. It works great and just passes the selected/searched items in the URL like this www.mydomain.com/products/cid:1/mid:3/terms:these%20terms where cid is category id, and mid is manufacturer id.
I created pages that allow you to click a category to find all products in that category, but I can't get the category select box, in the element, to select the category of the page it is on. It works if I use the same URL structure as my element submits but I want a clean URL for SEO so I setup the following custom route:
/**
* Categories
*/
Router::connect(
'/products/category/:cid-:slug', // E.g. /products/category/3-my_category
array('controller' => 'products', 'action' => 'category'),
array(
'pass' => array('cid', 'slug'),
'cid' => '[0-9]+'
)
);
this results in a nice looking URL but doesn't pre-select the value of my select list.
I was able to get it working with the code below in my element, but it seems "hacky/clunky"
if(isset($this->params['named']['cid']) && !empty($this->params['named']['cid'])){
echo $this->Form->input('cid', array('label' => false, 'default' => $this->params['named']['cid'], 'options' => $categories, 'empty' => ' ( Category ) '));
}elseif(isset($this->params['pass']['0']) && !empty($this->params['pass']['0'])){
echo $this->Form->input('cid', array('label' => false, 'default' => $this->params['pass']['0'], 'options' => $categories, 'empty' => ' ( Category ) '));
}else{
echo $this->Form->input('cid', array('label' => false, 'options' => $categories, 'empty' => ' ( Category ) '));
}
Also, in my controller I've tried this:
$this->params['named']['cid'] = $this->params['pass']['0'];
but I get this error: Indirect modification of overloaded element of CakeRequest has no effect
I believe the plugin automatically sets the selected value if using named params, unless thats a default behavior of cake. How can I convert the passed params to named params, or can I force my plugin to use passed params?
output from var_dump($this->$params):
object(CakeRequest)[9]
public 'params' =>
array
'plugin' => null
'controller' => string 'products' (length=8)
'action' => string 'category' (length=8)
'named' =>
array
empty
'pass' =>
array
0 => string '2' (length=1)
1 => string 'This_and_that' (length=13)
'cid' => string '2' (length=1)
'slug' => string 'This_and_that' (length=13)
public 'data' =>
array
empty
public 'query' =>
array
empty
Thanks
CakePHP appears to have a function to translate a requested URL and determine what controller and action to perform, seeing this must be performed with each http request.
Is there a way I can utilize this process within a controller or elsewhere in the system? The best outcome would be to have a function where I input a URL string, and the response is an array with controller details. eg:
$url_route = RouteFunction('/page/url/here');
// $url_route = array(
// 'controller' => 'page',
// 'action' => 'display',
// 'pass' => array('url', 'here')
// );
For this you can use Router::parse().
For example:
$route = Router::parse('/users/view/21');
debug($route);
will by default output:
array(
'controller' => 'users',
'action' => 'view',
'named' => array(),
'pass' => array(
(int) 0 => '21'
),
'plugin' => null
)
CakePHP 2.2.3
I have something like this:
$this->Html->link('here',
array(
'controller' => 'biz',
'action' => 'search',
'range' => '1+3'),
array('escape' => false));
When I click on this link the url will be encoded like this:
/biz/search/range:1%2B3
But I need
/biz/search/range:1+3
Is there any way to switch off url encoding or should I change my controller which parses the named parameter??
Try using:
$this->Html->link('here',
array(
'controller' => 'biz',
'action' => 'search',
'range' => '1\+3'),
array('escape' => '\'));
Simply can you try this
//search.ctp
echo $this->Html->link('here', '/biz/search/range:1+3');
Receive this in controller
//BizController.php
public function search() {
var_dump($this->request->params['named']);
// do something
}
I want to test a function with this header:
public function includeNumComments($posts){
Where $post is an array of data.
I wonder how can i test the method passing it an array of posts.
I have tried things like this, but it doesn't work:
$result = $this->testAction("/comments/includeNumComments/", array('data' => $posts));
$result = $this->testAction("/comments/includeNumComments/", array($posts));
Thanks
Here's the correct case, it worked for me. Hope it helps:
public function testAddUser() {
$data = array(
'User' => array(
'id' => 12,
'username' => 'testname1',
'password' => 'Pass#123!',
'email' => 'test#example.com'
)
);
$result = $this->testAction(
'/users/add',
array('data' => $data, 'method' => 'post')
);
debug($result);
}
That's not really using testAction then, because you can't pass an array via HTTP. There'd be no way to do this via a form or link on a website.
You can just test it as a normal function:
$result = $this->CommentsController->includeNumComments($posts);