RESTful CodeIgniter
今天学习RESTful时发现的文章:
使用CodeIgniter框架,为你的web应用程序建立RESTful API服务,并演示如何让创建的API和其他RESTful风格的webservices
我们提供了相关的基础框架示例程序下载,以方便本文的接下来的讨论。下载地址在:http://github.com/philsturgeon/codeigniter-restserver,如下图,只需要点download sources或者使用 Git clone 一份下来就可以进行测试了
这里有五个示例,其中每个示例的链接都是以RESETful的形式给出的,下面我们分析其含义。注意这些都是由application/controller/example_api.php这个控制器产生的,我们分析下这些相关的URL,可以看到这种形式很象CodeIgniter中的MVC架构的链接,但要注意到,传统的CodeIgniter中的有点不同,在链接的最后一部分,我们称为Resource资源。有一点RESTful知识的朋友可能知道,在RESTful中,把要操作的对象都叫资源,而且对资源是通过HTTP方式进行相关操作,比如增加,删除,编辑和查询
// 在 application/config/routes.php 后面(或合适位置)加上这一行
map_resources('users');
///////////////////////////////////////////////////////////////////////////////
// 如果你不需要自定义额外的 url 规则,请无视下面的代码。。。
///////////////////////////////////////////////////////////////////////////////
// custom action handles GET request
map_resources('GET', 'users/(:id)/custom_action', 'users/custom_action/$1');
// some other custom action mappings...
// custom action handles PUT request
//map_resources('PUT', 'users/(:id)/custom_action', 'sync_sessions/custom_action/$1');
// custom action handles all requests (GET, POST, PUT, DELETE)
//map_resources('users/(:id)/custom_action', 'sync_sessions/custom_action/$1');
然后 controller 里就可以像 Rails 一样啦(除了 new, 因为 php 语言的限制,没办法 ):
class Users extends Controller
{
function Users()
{
parent::Controller();
}
// GET /users
function index()
{
echo __METHOD__ . "
\n" . $_SERVER['REQUEST_METHOD'] . " /users\n";
}
// GET /users/12345
function show($id)
{
echo __METHOD__ . "
\n" . $_SERVER['REQUEST_METHOD'] . " /users/{$id}\n";
}
// GET /users/new
// I have to use new_form as method name because "new" is a keyword in php
function new_form()
{
echo __METHOD__ . "
\n" . $_SERVER['REQUEST_METHOD'] . " /users/new\n";
}
// GET /users/12345/edit
function edit($id)
{
echo __METHOD__ . "
\n" . $_SERVER['REQUEST_METHOD'] . " /users/{$id}/edit\n";
}
// POST /users
function create()
{
echo __METHOD__ . "
\n" . $_SERVER['REQUEST_METHOD'] . " /users\n";
}
// PUT /users/12345
function update($id)
{
echo __METHOD__ . "
\n" . $_SERVER['REQUEST_METHOD'] . " /users/{$id}\n";
}
// DELETE /users/12345
function delete($id)
{
echo __METHOD__ . "
\n" . $_SERVER['REQUEST_METHOD'] . " /users/{$id}\n";
}
// GET /users/12345/custom_action
function custom_action($id)
{
echo __METHOD__ . "
\n" . $_SERVER['REQUEST_METHOD'] . " /users/{$id}/custom_action\n";
}
}
看到这里如果你感兴趣的话,可以继续往下看怎么实现了。其实非常简单,只有一个 MY_Router.php 文件,不到 100 行的代码(不计算空行和注释的话)。安装也很简单:只需要把这个 MY_Router.php 放到 application/libraries 目录下就万事大吉了。 代码逻辑我就不一一解释了,里面有注释,逻辑也简单,相信每个人都能看懂。
/**
* RESTful-CodeIgniter
*
* A RESTful url router library for CodeIgniter
*
* @author ZHENJiNG LiANG (liangzhenjing_N_O_S_P_A_M@gmail.com)
* @license BSD license
* @link http://liang.eu/web-dev/php/restful-style-url-in-codeigniter
*/
///////////////////////////////////////////////////////////////////////////////
// NOTE:
// This Library added two macros:
// :id as [^/]+ in order to match non-numeric id field,
// :uuid to match UUID (aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee)
//
// :any and :num remain the same
// See code below for details
// You can change at will
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// map_resources() --> Return all routes
// map_resources($controller_name) --> Map default restful routes
// map_resources($method, $pattern, $replace) --> Add a custom route
///////////////////////////////////////////////////////////////////////////
function map_resources()
{
static $routes = array();
$arg_num = func_num_args();
if(0 == $arg_num)
{
return $routes;
}
elseif(1 == $arg_num)
{
// map_resources($controller_name) --> return all routes
$controller = func_get_arg(0);
// Generate RESTful url match patterns
$routes['GET']["{$controller}"] = "{$controller}/index";
$routes['GET']["{$controller}/new"] = "{$controller}/new_form";
$routes['GET']["{$controller}/(:id)"] = "{$controller}/show/$1";
$routes['GET']["{$controller}/(:id)/edit"] = "{$controller}/edit/$1";
$routes['POST']["{$controller}"] = "{$controller}/create";
$routes['PUT' ]["{$controller}/(:id)"] = "{$controller}/update/$1";
$routes['DELETE']["{$controller}/(:id)"] = "{$controller}/delete/$1";
}
elseif(2 == $arg_num)
{
// Custom url routing
$args = func_get_args();
$pattern = $args[0];
$replace = $args[1];
$routes['GET'][$pattern] = $replace;
$routes['POST'][$pattern] = $replace;
$routes['PUT'][$pattern] = $replace;
$routes['POST'][$pattern] = $replace;
}
elseif(3 == $arg_num)
{
// Custom url routing
$args = func_get_args();
$method = $args[0];
$pattern = $args[1];
$replace = $args[2];
$routes[$method][$pattern] = $replace;
}
}
///////////////////////////////////////////////////////////////////////////
// RESTful style url router
///////////////////////////////////////////////////////////////////////////
class MY_Router extends CI_Router
{
function MY_Router()
{
// HACK: support overridding REQUEST_METHOD by posting a _method parameter
if($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['_method']))
{
$_SERVER['REQUEST_METHOD'] = strtoupper($_POST['_method']);
}
elseif(isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']))
{
$_SERVER['REQUEST_METHOD'] = strtoupper($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']);
}
parent::CI_Router();
}
// Overrides CI_Router::_parse_routes.
// RESTful style url matching
function _parse_routes()
{
$rest_routes = map_resources();
// we do this for performence
if (empty($rest_routes) && count($this->routes) == 1)
{
$this->_set_request($this->uri->segments);
return;
}
// also this...
$uri = implode('/', $this->uri->segments);
if (isset($this->routes[$uri]))
{
$this->_set_request(explode('/', $this->routes[$uri]));
return;
}
// RESTful url matching...
$request_method = $_SERVER['REQUEST_METHOD'];
$routes = (isset($rest_routes[$request_method]) && $rest_routes[$request_method]) ? $rest_routes[$request_method] : array();
foreach($routes as $pattern => $replace)
{
$pattern = str_replace(':id', '[^/]+', $pattern); // use this to match non-numeric id field
$pattern = str_replace(':any', '.+', $pattern);
$pattern = str_replace(':num', '[0-9]+', $pattern);
$pattern = str_replace(':uuid', '[a-zA-Z0-9]{8}(-[a-zA-Z0-9]{4}){3}-[a-zA-Z0-9]{12}', $pattern);
// Does the RegEx match?
if (preg_match("#^{$pattern}$#", $uri))
{
// Do we have a back-reference?
if (strpos($replace, '$') !== FALSE && strpos($pattern, '(') !== FALSE)
{
$replace = preg_replace("#^{$pattern}$#", $replace, $uri);
}
// we are done
$this->_set_request(explode('/', $replace));
return;
}
}
// if non of the rules match, then go on...
parent::_parse_routes();
}
}
本文转自 :http://liang.eu/ 博客
上一篇: jQuery事件绑定子元素继承问题
下一篇: git日常操作