Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

limboy/resty

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

9 Commits

Repository files navigation

关于REST的介绍可以参考我之前的文章,总体说来,REST是web发展的趋势,而PHP是web开发的利器,但我找了一遍,只找到了两个PHP REST框架(不包括那些以MVC为核心,同时又支持REST的框架),一个是Tonic,架构理念我比较认同,但代码质量实在不敢恭维。还有一个是Recess,在我看来,它有点复杂化了,把不该rest做的事也做了。在这种情况下,我只能自己动手,丰衣足食了。

RESTY简介

RESTY的流程很简单,获取Request单例,然后执行exec方法,该方法里会调用Route来解析URI获取相应的Resource,然后实例化Resource,触发相应的HTTP方法,最后返回一个Response对象,Response执行output方法就输出了结果。听起来好像一点都不简单,哈哈,还是来大概看一下代码吧

index.php

try {
	Request::instance()->exec()->output();
} catch (Route_Exception $e) {
	Response::instance()
		->set_status(404)
		->set_body(array(
			'error' => 'Resource Not Found',
			'Request' => $_SERVER['REQUEST_URI'],
		))
		->output()
		;
}

request.php

public function exec()
{
	$class_name = 'Resource_'.str_replace('/', '_', $this->get_resource());
	$class = new ReflectionClass($class_name);
	$resource = $class->newInstance($this);
	$class->getMethod('before')->invoke($resource);
	$class->getMethod($this->request_method)->invoke($resource);
	$class->getMethod('after')->invoke($resource);
	
	$response = Response::instance();
	$response->set_body($resource->get_data());
	return $response;
}

response.php

public function output() 
{
	$this->_content_encoding();
	header('Content-type:application/json;charset=utf-8');
	header('Status:'.$this->_status.' '.$this->_messages[$this->_status]);
	header('Content-Length: '.strlen($this->_body));
	foreach($this->_header as $key => $val)
	{
		header($key.':'.$val);
	}
	echo $this->_body;
}

RESTY特性

轻量级

RESTY包含了核心的Request/Resource/Response/Route/Config/Validation功能,没有其他多余的部件,如Controller/View等等,很纯粹。一个工具应该把一件事做好,同时提供接口,这也是RESTY的哲学。

使用方便

使用时,只需定义好uri对应的Resource,然后编写Resource就行了,其他的事RESTY会帮你搞定。

config/resource.php demo

return array(
	'/example/(?<id>[0-9]+)' => 'example',
	'/example/foo/(?<name>[a-zA-Z_0-9]+)' => 'example/foo',
);

可以看到uri支持正则,没错,原生的php正则。resource部分对应resource文件的路径(不包括后缀)

resource/example.php

class Resource_Example extends Resource
{
	public function get()
	{
		/* set etag
		Response::instance()
			->if_none_match(md5('hello'))
			->add_etag(md5('hello'))
			;
		//*/
		if ($this->validate())
		{
			$this->_data = $this->get_data();
		}
		else 
		{
			$this->_data = array('error' => implode(',', $this->getErrors()), 'request' => $_SERVER['REQUEST_URI']);
		}
	}
	public function post()
	{
		$this->_data = array_merge($this->get_data(), array('type' => 'post'));
	}
}

每一个资源对应4个http方法。RESTY还很贴心地提供了Validation部件(基本上是直接从Kohana中K过来的),方便对数据进行校验。

易扩展

system/classes文件夹下的类文件,都可以在app/classes文件夹下扩展,而且使用时不用做任何修改。假设你之前已经写了不少Resource,忽然想到要扩展系统的Resource类,正常的做法是定义一个MY_Resource之类的类文件来扩展系统的Resource类,然后使用时使用MY_Resource而不是Resource。但这样就会有个问题,之前使用的Resource类都要做修改了,可谓牵一发而动全身。RESTY就方便了,同样要扩展Resource类,只要在app/classes下新建一个resource.php文件,然后扩展Resty_Resource类即可。

class Resource extends Resty_Resource
{
	public function foo()
	{
		//...
	}
}

这样使用时还是一样的Resource类,但却多了foo方法。这也是从Kohana学到的无缝扩展大法(题外话:Kohana真是个不错的框架,各位不妨一试)。原理就是在类自动加载时会先去app/classes文件夹下去找,如果没找到的话再去system/classes下找。

验证功能

作为一个比较完整的REST框架,Validation还是不能少的,为了不重复制造轮子,直接把Kohana的验证类搬了过来,稍作修改。

配置:config/validation.php

return array(
	'example' => array(
		'get' => array(
			'filters' => array(
				'id' => array(
					'trim' => null,
				),
			),
			'rules' => array(
				'id' => array(
					'not_empty' => null,
					'min_length' => array(2),
					'digit' => null,
				),
			),
		),
	),
);

错误提示:config/message.php

return array( 'example' => array( 'id' => array( 'digit' => 'id必须是数字', 'not_empty' => 'id不能为空', 'min_length' => 'id长度至少为:value', ), ), );

Config功能

config文件如上面所示,就是返回一个数组。使用也很简单:

// 获取config/message.php文件的example key对应的内容
Config::get('message.example');
// 设置config(不会写入到文件,只在一个http request有效)
Config::set('message.example.id.digit', 'id can be anything');

About

a lighweight php rest framework

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

AltStyle によって変換されたページ (->オリジナル) /