Rhys
Rhys

Reputation: 1581

CakePHP's trailing star routing syntax appears to double up arguments in the HTML Helper

I have previously used CakePHP's routing functionality with the greedy star, allowing all the additional arguments in the URL to be pushed through to the requested controller. This works fine, and as expected with the HTML Helper.

Referring to the CakePHP book the trailing star syntax (double wildcard, **) performs the same operation, but combines every additional argument into a single string. This also works well when I directly go to a URL that uses this method, but the HTML Helper seems to double up the arguments, as seen below:

Router::connect(
  '/view/**', 
  array('controller' => 'thing', 'action' => 'view')
);

$this->Html->link(
  'title here', 
  array('controller' => 'thing', 'action' => 'view', 'abc', 'def'
));

http://website.com/thing/view/abc/defabc/def

whereas it should be

http://website.com/controller/view/abc/def

Upvotes: 0

Views: 315

Answers (1)

jeremyharris
jeremyharris

Reputation: 7882

The /** is more for parsing, not for matching. Parsing is when you're taking the string version of the url and turning it into an array that Cake uses to point to the resource, while matching is taking an array-based url and turning into a string based on your routes.

Router::connect(
  '/view/**', 
  array('controller' => 'thing', 'action' => 'view')
);
// input
Router::parse('/view/something/here/for/you');
// output
array(
  'controller' => 'thing',
  'action' => 'view',
  'pass' => array('something/here/for/you'),
  'named' => array()
);

// input
Router::url(array(
  'controller' => 'thing',
  'action' => 'view',
  'something',
  'here'
));
// output
/view/something/heresomething/here

// input
Router::url(array(
  'controller' => 'thing',
  'action' => 'view',
  'something/here'
));
// output
/view/something%2Fheresomething%2Fhere

The second and third examples are obviously not right. I'm guessing it's a bug with the router. Even if it constructed the url correctly, it would be impossible to parse it because the /** would turn something/heresomething/here into a single passed argument.

As a workaround, you can exclude all passed arguments and prepend it to your link:

$url = Router::url(array('controller' => 'thing', 'action' => 'view'));
$this->Html->link(
  'title here', 
  $url . 'abc/def'
));
// ends up: /view/abc/def

The abc/def would then be parsed into a single passed argument.

Upvotes: 1

Related Questions