可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Consider this route in bootstrap.php
...
Route::set('crud', 'staff/<controller>(/<action>(/<id>))', array(
'controller' => '(activities|users|default-emails)',
'action' => '(new|view|modify|delete)',
'id' => '\d+'
))->defaults(array(
'directory' => 'staff',
'action' => 'view'
));
The default-emails
is trying to run the action_default-emails()
method which obviously doesn't and can't exist.
What part of Kohana should I extend to map that hyphen into a underscore internally?
Should I be concerned that if I do do this, then it will be accessible via both _
and -
delimited routes?
Thanks.
回答1:
The simplest is to hack Kohana_Request::execute()@1112
$class->getMethod('action_'.$action)->invokeArgs($controller, $this->_params);
change to
$class->getMethod('action_'.str_replace('-', '_', $action))->invokeArgs($controller, $this->_params);
But you understand, that you have to do this patch in each next kohana version.
More harmless could be to extend Kohana_Route::matches()
class Route extends Kohana_Route
{
public function matches($uri)
{
$matches = parent::matches($uri);
if (isset($matches['action']))
{
$matches['action'] = str_replace('-', '_', $matches['action'];
}
return $matches;
}
}
Did not check, but I bet it should work.
回答2:
My solution for Kohana 3.2 for routing hyphenated actions to the appropriate underscored method:
Extend Kohana_Route and insert this code
if($key == 'action')
{
$params[$key] = str_replace('-','_',$value);
}
else
{
$params[$key] = $value;
}
Full Solution: Create a file route.php in application/classes/
<?php defined('SYSPATH') or die('No direct script access.');
class Route extends Kohana_Route
{
public function matches($uri)
{
if ($this->_callback)
{
$closure = $this->_callback;
$params = call_user_func($closure, $uri);
if ( ! is_array($params))
return FALSE;
}
else
{
if ( ! preg_match($this->_route_regex, $uri, $matches))
return FALSE;
$params = array();
foreach ($matches as $key => $value)
{
if (is_int($key))
{
// Skip all unnamed keys
continue;
}
// Set the value for all matched keys
if($key == 'action')
{
$params[$key] = str_replace('-','_',$value);
}
else
{
$params[$key] = $value;
}
}
}
foreach ($this->_defaults as $key => $value)
{
if ( ! isset($params[$key]) OR $params[$key] === '')
{
// Set default values for any key that was not matched
$params[$key] = $value;
}
}
return $params;
}
}
回答3:
Since Kohana 3.3 came out this method no longer works. I have found a solution that, so far, works for me.
When upgrading to 3.3, you don't need to edit the Internal.php request file. Instead, you can create a Route Filter. All you need to do is replace hyphen in the action to an underscore.
Route::set('default', '(<controller>(/<action>(/<id>)))')
->filter(function($route, $params, $request) {
// Replacing the hyphens for underscores.
$params['action'] = str_replace('-', '_', $params['action']);
return $params; // Returning an array will replace the parameters.
})
->defaults(array(
'controller' => 'welcome',
'action' => 'index',
));
This obviously only works for the methods. However, if you explore a little further, you can create a better function for the directory, controller, etc.
回答4:
An update to zerkms's method. In Kohana 3.2, you need to edit the file system/classes/kohana/request/client/internal.php
line 106.
Replace:
$action = $request->action();
By:
$action = str_replace('-', '_', $request->action());
I dislike hacking frameworks but this is by far the simplest and most reliable solution. Renaming the action in the Route class can lead to all sorts of troubles, because the action will then sometime be called my_action (internally) and sometime my-action (in links).