RESTful Routing

  1. Would there be any plans in the future to offer support for RESTful routing?

  2. If not anytime "soon", what might be best approach to implement this (where to start)?

Specifically, away we can specify the HTTP METHOD (POST/PUT/UPDATE/DELETE) in the routing rules so the route mapping can be based on that also.

For example, to support resource oriented architecture for creating a RESTful API, we want multiple patterns of /articles to be routed to different controller/actions based on the HTTP METHOD.

Today in Yii, a route rules looks like this:


'rules'=>array(                 

    'pattern1'=>'route1',                 

    'pattern2'=>'route2',                 

    'pattern3'=>'route3',             

),

Maybe offer something like (maybe not best approach, but some way to specify the method in rules)


'rules'=>array(

    array('pattern1' => 'route1', 'http_method1' => 'METHOD1'),

    array('pattern2' => 'route1', 'http_method2' => 'METHOD2'),                 

),

More concretely:


'rules'=>array(

    array('articles' => 'articles/index', 'http_method' => 'GET'),

    array('articles' => 'articles/create', 'http_method' => 'POST'), 

    array('articles/<id:>' => 'articles/update', 'http_method' => 'PUT'),     

    array('articles' => 'articles/delete', 'http_method' => 'DELETE'),  

    array('articles/<id:>' => 'articles/show', 'http_method' => 'GET'),         

),

We could even make it a convenience through conventions by defining a "resource" in urlManager

such that those combination of patterns/routes/http_method are automatically generated:




 'urlManager'=>array(

            'urlFormat'=>'path',

            'rules'=>array(

                'pattern1'=>'route1',

                'pattern2'=>'route2',

                'pattern3'=>'route3',

            ),

            'resources' => array('articles'),  // would automatically support the routes in concrete example

        ),



Great, I think it is so well if Yii support Restful routing just like Rails。 Looking forward for this.

+1 for this.

+1

Maybe it is better to make CUrlManager plug-able. Similar to how CLogRouter work. Maybe someone can extend CUrlManager and implement plug-gable architecture.

+1, also need the crud generator to generate the restful api too.

+1

http://www.yiiframework.com/forum/index.php?/topic/14172-api-application-programming-interface/

Im about to finish an extension and it will be avaliable soon

rules format will be like the following:




	'rules'=>array(

    	//rules applied to all kind of requests if a specific verbs/method rule does not match/trigger first

    	'<_c:\w*>/<_a:\w+>/<id:\d+>'=>'<_c>/<_a>',

    	//rules for post requests

    	'@post'=>array(

        	'<_c:\w+>'=>'<_c>/create',

        	'<_c:\w+>/<id:\d+>'=>'<_c>/update',

    	),

    	'@put'=>array(

        	'<_c:\w+>'=>'<_c>/create',

        	'<_c:\w+>/<id:\d+>'=>'<_c>/update',

    	),

    	'@get'=>array(

        	'<_c:\w+>/<id:\d+>'=>'<_c>/update',

        	'<_c:\w+>/<_a:\w+>/<q:\w+>'=>'<_c>/search',

    	),

    	//case insensitive

    	'@DELETE'=>array(

        	'<_c:\w+>'=>'error/400',

        	'<_c:\w+>/<id:\d+>'=>'<_c>/delete',

    	),

    	//rule is a string, which means that all requests go to a fixed route 

    	'@HEAd'=>'error/501'

	)




any sugestions ?

Interesting! :)

I have my desktop full of REST php stuff and am working on my own (simple) solution.

I’ll be interested in checking out your extension.

Any reason why the @'s are not uppercase all of them?

For consistency they probably should be.

Is it going to be applied to all routes/controllers?

Or is it going through an api controller?

Its to facilitate for the user, I prefer to work this way in case of me or anyone misstype or forget which way is the right way

Good idea, I had just finished but now im about to add your sugestion

Initially it was for all requests, since my restful system is a different one than my application/user system

What do you think of using it this way ?




'rules'=>array(

   	//rules for the rest controller

   	'rest/*'=>array(

        	//rules for post requests

        	'@post'=>array(

                	'<_c:\w+>'=>'<_c>/create',

                	'<_c:\w+>/<id:\d+>'=>'<_c>/update',

        	),

        	'@get'=>array(

                	'<_c:\w+>/<id:\d+>'=>'<_c>/update',

                	'<_c:\w+>/<_a:\w+>/<q:\w+>'=>'<_c>/search',

        	),

        	//...

   	),

   	//other/normal rules

   	'<_m:\w+>/<_c:\w+>/<_a:\w+>/<id:\d+>'=>'<_m>/<_c>/<_a>',

   	'<_m:\w+>/<_c:\w+>/<id:\d+>'=>'<_m>/<_c>',

   	'<_m:\w+>/<id:\d+>'=>'<_m>',

	)



Looks good. :)

I’ve thought of letting my rest app component use filters so that you can choose what actions you want to be rest’ed.

That way there’s no need to create any additional url rules.

Just run Yii::app()->rest->handleRequest() on the actions before running them normally.

I think.

My implementation is probably much, much simpler than yours.

Still haven’t thought of access control.

Maybe just an API key the user has generated beforehand?

The way I do my access controll in a rest server is the following :

1-client with ip Y logs in/register and gets a key X

2-client request content using its key , server check if pair key and ip matches with the ones stored previously in db

3-server generates new key, stores it and the ip in db and then send it to the user with the requested content

4-client stores the new key in db for further use

repeat process from step 2

about the url rules, ill stick with my first version, otherwise it will give me much more trouble than i want to have right now

its actually pretty simple:




<?php

class VerbUrlManager extends CUrlManager{

	protected function processRules(){

    	$rules=array();

		$method=strtolower(Yii::app()->getRequest()->getRequestType());

    	//transform rules keys to lowercase

    	$this->rules=array_combine(array_map(array($this,'__atToLowerCase'), array_keys($this->rules)),array_values($this->rules));

    	if(in_array("@{$method}", $this->rules)){

        	$rules=$this->rules["@{$method}"];

    	}

    	//add the default rules

    	if(is_array($rules))

        	foreach($this->rules as $k=>$rule)

            	if(substr($k,0,1)!=='@')

                	$rules[$k]=$rule;

            	

    	

    	$this->rules=$rules;

    	parent::processRules();

	}

	private function __atToLowerCase($str){

    	if(substr($str,0,1)==="@")

        	return strtolower($str);

    	return $str;

	}

}



and then in options set


'urlManager'=>array(

        	'class'=>'VerbUrlManager',