Yii Framework Forum: Adding dash to actions. (e.g. http://yii.com/admin/add-account) - Yii Framework Forum

Jump to content

  • (2 Pages)
  • +
  • 1
  • 2
  • You cannot start a new topic
  • You cannot reply to this topic

Adding dash to actions. (e.g. http://yii.com/admin/add-account) Rate Topic: -----

#1 User is offline   x3rx3s 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 19
  • Joined: 31-October 10

Posted 10 January 2011 - 03:15 PM

Hi,

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
0

#2 User is offline   twisted1919 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 643
  • Joined: 23-October 10
  • Location:Romania

Posted 10 January 2011 - 03:28 PM

In order to have this kind of functionality working i have something like :

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 ? :)
1

#3 User is offline   x3rx3s 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 19
  • Joined: 31-October 10

Posted 10 January 2011 - 03:38 PM

Awesome, wish that was built-in, but awesome nonetheless.

Thanks!
1

#4 User is offline   GSTAR 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 1,035
  • Joined: 30-October 09
  • Location:UK

Posted 10 January 2011 - 04:39 PM

Yes - should definitely be built-in and handled automatically!
0

#5 User is offline   x3rx3s 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 19
  • Joined: 31-October 10

Posted 10 January 2011 - 04:43 PM

Just realize I can't use your method...

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.
0

#6 User is offline   twisted1919 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 643
  • Joined: 23-October 10
  • Location:Romania

Posted 10 January 2011 - 04:50 PM

Be sure that you have correct routing rules for getting the ID.
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.
0

#7 User is offline   twisted1919 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 643
  • Joined: 23-October 10
  • Location:Romania

Posted 10 January 2011 - 04:53 PM

Ah, i haven't tried yet, but maybe you can do something like
//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.
1

#8 User is offline   alex-w 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 223
  • Joined: 25-November 10

Posted 10 January 2011 - 04:54 PM

Think you could also use the actions method of the controller.
http://www.yiiframew...#actions-detail
1

#9 User is offline   x3rx3s 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 19
  • Joined: 31-October 10

Posted 10 January 2011 - 04:57 PM

Thanks, I got this error though:
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


View Posttwisted1919, on 10 January 2011 - 04:53 PM, said:

Ah, i haven't tried yet, but maybe you can do something like
//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.

0

#10 User is offline   x3rx3s 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 19
  • Joined: 31-October 10

Posted 10 January 2011 - 05:05 PM

Alright, got it.

This works:

$this->run($action);
0

#11 User is offline   twisted1919 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 643
  • Joined: 23-October 10
  • Location:Romania

Posted 10 January 2011 - 05:09 PM

If you're still here can u see if this works:
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.
0

#12 User is offline   x3rx3s 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 19
  • Joined: 31-October 10

Posted 10 January 2011 - 05:13 PM

runAction expects a CAction object, a string won't work that's why I had to use ->run().
0

#13 User is offline   twisted1919 

  • Master Member
  • PipPipPipPip
  • Yii
  • Group: Members
  • Posts: 643
  • Joined: 23-October 10
  • Location:Romania

Posted 10 January 2011 - 05:15 PM

ah okay, makes sense this way, i don't have access at my yii project right now that's why i cannot test, but i'm glad we sorted it out in the end.
1

#14 User is offline   hk1 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 5
  • Joined: 09-January 11

Posted 10 January 2011 - 06:19 PM

This is also an important feature to me for SEO purposes. I wish that Yii would have built-in, native support for this option.
0

#15 User is offline   lubosdz 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 115
  • Joined: 25-July 10
  • Location:Slovakia, Bratislava

Posted 14 June 2011 - 05:18 AM

Here is my final solution to support action names with dashes.
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
Yii extension: Captcha Extended

Greatest discoveries in 22nd century will be about the gravitation. | http://www.synet.sk | http://ipdf.sk
1

#16 User is offline   yuripave 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 1
  • Joined: 06-March 11

Posted 21 June 2011 - 10:13 AM

Just want to share my workaround because overwriting missingAction is not enough for me because I would like to have dashed controller as well.
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);
    }
}

0

#17 User is offline   enrico.detoma 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 3
  • Joined: 15-March 09

Posted 18 January 2012 - 12:02 PM

My solution (which currently seems to work) to map from /dash-controller/dash-action to /DashController/DashAction is:

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.
0

#18 User is offline   gazbond 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 61
  • Joined: 02-November 09
  • Location:London, UK

Posted 11 February 2012 - 02:18 PM

Here's my solution for converting camel case to underscores and back again:
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;
	}
}

0

#19 User is offline   acorncom 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 100
  • Joined: 25-February 11
  • Location:CO, USA

Posted 02 March 2012 - 06:22 PM

Thanks gazbond, that just helped a lot on my end! I've finally got easy creation/use of hyphenated links!
0

#20 User is offline   gazbond 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 61
  • Joined: 02-November 09
  • Location:London, UK

Posted 29 March 2012 - 02:17 AM

View Postfr0d0z, on 02 March 2012 - 06:22 PM, said:

Thanks gazbond, that just helped a lot on my end! I've finally got easy creation/use of hyphenated links!


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!
0

Share this topic:


  • (2 Pages)
  • +
  • 1
  • 2
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users