Adding dash to actions. (e.g. http://yii.com/admin/add-account)
#1
Posted 10 January 2011 - 03:15 PM
How do I name my method for my action if I want the url to use a dash?
e.g. http://yii.com/admin/add-account
public function actionAdd_Account() // Tried this, didn't work.
Thanks
#2
Posted 10 January 2011 - 03:28 PM
class Xyx extends CController{
// this is what does all the hard work
public function missingAction($action)
{
$action=str_replace('-','_',$action);
$action='action'.ucfirst(strtolower($action));
if(method_exists($this,$action))
$this->$action();
else
$this->actionIndex();
}
public function actionMy_fancy_action_here()
{
//the url can be
// A) : /xyz/my-fancy-action-here
// B) : /xyz/my_fancy_action_here
}
}
Pretty neat ha ?
#3
Posted 10 January 2011 - 03:38 PM
Thanks!
#5
Posted 10 January 2011 - 04:43 PM
I can't access this variable ($this->action->id) after calling $this->$action
print_r($this->action) // This won't work inside the actual action method.
#6
Posted 10 January 2011 - 04:50 PM
Also, the id can be retrieved via $_GET['id'];
it is perfectly normal to not access $this->action->id when using the method i shown to you, because the action doesn't actually exists, but it is the only way to get this functionality.
#7
Posted 10 January 2011 - 04:53 PM
//http://www.yiiframework.com/doc/api/1.1/CController#setAction-detail
public function missingAction($action)
{
$action=str_replace('-','_',$action);
$action='action'.ucfirst(strtolower($action));
if(method_exists($this,$action))
{
$this->setAction($action);//see api link above
$this->$action();
}
else
$this->actionIndex();
}
Let me know if it works this way, i haven't tried.
#8
Posted 10 January 2011 - 04:54 PM
http://www.yiiframew...#actions-detail
#9
Posted 10 January 2011 - 04:57 PM
PHP Fatal error: Call to a member function getId() on a non-object in /framework/yii-1.1.5.r2654/web/CController.php on line 937
twisted1919, on 10 January 2011 - 04:53 PM, said:
//http://www.yiiframework.com/doc/api/1.1/CController#setAction-detail
public function missingAction($action)
{
$action=str_replace('-','_',$action);
$action='action'.ucfirst(strtolower($action));
if(method_exists($this,$action))
{
$this->setAction($action);//see api link above
$this->$action();
}
else
$this->actionIndex();
}
Let me know if it works this way, i haven't tried.
#11
Posted 10 January 2011 - 05:09 PM
public function missingAction($action)
{
$action=str_replace('-','_',$action);
if(method_exists($this,$action))
$this->runAction($action);
else
$this->runAction('index');
}
If it does, then this is the right way to do it .
Let me know.
#12
Posted 10 January 2011 - 05:13 PM
#13
Posted 10 January 2011 - 05:15 PM
#14
Posted 10 January 2011 - 06:19 PM
#15
Posted 14 June 2011 - 05:18 AM
It checks also controller's actions and handles action name like my-action => actionMyAction which is compatible with Zend Framework implementation (intuitive name convention).
/**
* Catch all action - used as a workaround to support dashed action names like my-action => actionMyAction (compatible with Zend Framework)
* @param string $action Action that was not found within this controller
*/
public function missingAction($action){
$action = explode('-', $action);
$action = array_map('strtolower', $action);
$action = array_map('ucfirst', $action);
$action = implode('',$action);
if(method_exists($this,'action'.$action) || array_key_exists('action'.$action, $this->actions())){
$this->setAction($action);
$this->run($action);
}else{
throw new CHttpException(404, Yii::t('main','Action "{action}" does not exist in "{controller}".', array(
'{action}' => 'action'.$action,
'{controller}' => get_class($this),
)));
}
}
Cheers
Lubos
Greatest discoveries in 22nd century will be about the gravitation. | Homepage: http://www.synet.sk
#16
Posted 21 June 2011 - 10:13 AM
Basically I stripped the dashes from the whole url where I got the idea somewhere from the forum by overwriting parseUrl() in UrlManager. (Please point me to that post so I can post this workaround there too)
But one thing is missing is that now the GET parameters with dashes using path will stripped as well and this is not desirable, we need to restore it somehow.
So this is my solution. Tested on 1.1.7. It may not work with future Yii version if those two methods handle differently later on.
With this UrlManager, if you has a url with /dash-controller/dash-action, then you will need DashcontrollerController under controllers and actionDashAction() within it.
Any better workarounds?
class UrlManager extends CUrlManager
{
private $hasDash = false;
// remove dash to map dashed url with undashed controller/action
public function parseUrl($request)
{
$url = parent::parseUrl($request);
$this->hasDash = substr_count($url, "-") > 0;
return $this->hasDash ? str_replace('-', '', $url) : $url;
}
// restore dash for GET parameters injected from path
public function parsePathInfo($pathInfo)
{
if($this->hasDash) {
$oldPath = explode("/", $pathInfo);
$paths = explode("/", Yii::app()->request->pathInfo);
for($i=0; $i < count($oldPath); $i++) {
$newPath[] = $oldPath[$i];
$key = array_search($oldPath[$i], $paths);
if($key!==false) {
$newPath[] = $paths[$key+1];
$i++;
}
}
$pathInfo = implode("/", $newPath);
}
parent::parsePathInfo($pathInfo);
}
}
#17
Posted 18 January 2012 - 12:02 PM
class UrlManager extends CUrlManager {
// remove dash to map dashed url with undashed controller/action
public function parseUrl($request)
{
$url = parent::parseUrl($request);
if (substr_count($url, "-") > 0) {
$url = explode('-', $url);
$url = array_map('strtolower', $url);
$url = array_map('ucfirst', $url);
$url = implode('',$url);
}
return $url;
}
}
To avoid having to use parsePathInfo to restore dash for GET parameters injected from path, I changed my rules from:
... '<controller:\w+>/<id:\d+>' => '<controller>/view', '<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>', '<controller:\w+>/<action:\w+>' => '<controller>/<action>', ...
to:
... '<controller:[0-9a-zA-Z_\-]+>/<id:\d+>' => '<controller>/view', '<controller:[0-9a-zA-Z_\-]+>/<action:[0-9a-zA-Z_\-]+>/<id:\d+>' => '<controller>/<action>', '<controller:[0-9a-zA-Z_\-]+>/<action:[0-9a-zA-Z_\-]+>' => '<controller>/<action>', ...
I.e. I replaced the \w with a regular expression which includes the dash.
#18
Posted 11 February 2012 - 02:18 PM
class UrlManager extends CUrlManager
{
public function createUrl($route,$params=array(),$ampersand='&')
{
if(preg_match('/[A-Z]/',$route)!==0)
{
$route=strtolower(preg_replace('/(?<=\\w)([A-Z])/','-\\1',$route));
}
return parent::createUrl($route,$params,$ampersand);
}
public function parseUrl($request)
{
$route=parent::parseUrl($request);
if(substr_count($route,'-')>0)
{
$route=lcfirst(str_replace(' ','',ucwords(str_replace('-',' ',$route))));
}
return $route;
}
}
#19
Posted 02 March 2012 - 06:22 PM
#20
Posted 29 March 2012 - 02:17 AM
fr0d0z, on 02 March 2012 - 06:22 PM, said:
I've just found a problem with this method - it gets applied to params and values as well
I'll be looking at fixing it sometime in the future but for now beware!

Help














