PHP 轻量级 REST框架

GITHUB:https://github.com/jacwright/RestServer

简介:

一个PHP REST服务器,用于提供非常轻量级的REST API。很容易上手。独立于其他库和框架。支持HTTP身份验证。

参考Zend Framework,该框架省略了Zend Framework MVC附带的大量类。还有一些有用的功能要添加(例如XML支持)。

RestServer到目前为止,该框架的解决方案是一个JSON REST服务器。添加对XML或其他格式的支持应该是微不足道的,但是必须假设您的对象在XML中的样子(XML-RPC样式,您自己的自定义XML格式等)。

首先,我们将查看您编写的用于处理请求的类,然后我们将查看如何在index.php文件中将它们绑定在一起。

使用教程:

从URL到类方法获取请求的映射都在类的doc-comments中。以下是处理某些用户操作的类的示例:

<?php

use \Jacwright\RestServer\RestException;

class TestController
{
/**
* Returns a JSON string object to the browser when hitting the root of the domain
*
* @url GET /
*/
public function test()
{
return "Hello World";
} /**
* Logs in a user with the given username and password POSTed. Though true
* REST doesn't believe in sessions, it is often desirable for an AJAX server.
*
* @url POST /login
*/
public function login()
{
$username = $_POST['username'];
$password = $_POST['password']; //@todo remove since it is not needed anywhere
return array("success" => "Logged in " . $username);
} /**
* Gets the user by id or current user
*
* @url GET /users/$id
* @url GET /users/current
*/
public function getUser($id = null)
{
// if ($id) {
// $user = User::load($id); // possible user loading method
// } else {
// $user = $_SESSION['user'];
// } return array("id" => $id, "name" => null); // serializes object into JSON
} /**
* Saves a user to the database
*
* @url POST /users
* @url PUT /users/$id
*/
public function saveUser($id = null, $data)
{
// ... validate $data properties such as $data->username, $data->firstName, etc.
// $data->id = $id;
// $user = User::saveUser($data); // saving the user to the database
$user = array("id" => $id, "name" => null);
return $user; // returning the updated or newly created user object
} /**
* Gets user list
*
* @url GET /users
*/
public function listUsers($query)
{
$users = array('Andra Combes', 'Valerie Shirkey', 'Manda Douse', 'Nobuko Fisch', 'Roger Hevey');
if (isset($query['search'])) {
$users = preg_grep("/{$query[search]}/i", $users);
}
return $users; // serializes object into JSON
} /**
* Get Charts
*
* @url GET /charts
* @url GET /charts/$id
* @url GET /charts/$id/$date
* @url GET /charts/$id/$date/$interval/
* @url GET /charts/$id/$date/$interval/$interval_months
*/
public function getCharts($id=null, $date=null, $interval = 30, $interval_months = 12)
{
echo "$id, $date, $interval, $interval_months";
} /**
* Throws an error
*
* @url GET /error
*/
public function throwError() {
throw new RestException(401, "Empty password not allowed");
}
}

让我们通过上面的TestController课程来讨论所展示的功能。首先我们来看看这个test方法。您会注意到docblock中有一种新的doc-comment标记。@url将URL映射到它下面的方法,格式如下:

@url <REQUEST_METHOD> <URL>

在这个特定的例子中,当某人在http://www.example.com/上进行GET时(假设example.com是我们的服务所在的位置),它将打印出来:

"Hello World"

这是JSON中字符串的有效表示。

继续下一个方法,login我们看到@url将任何POST映射到http://www.example.com/login到该login方法。从常规Web类型的POST获取数据与任何PHP应用程序相同,允许您将自己的验证或其他框架与此REST服务器结合使用。如果需要,也可以保留会话。虽然保持会话不是真正的REST风格,但我们通常只需要一个REST服务器来为我们的ajax应用程序提供数据,并且使用会话比使用RESTful更容易。

接下来我们有了我们的getUser方法(你会注意到我命名我的方法并不重要,因为我们的@url指令定义了哪些URL映射到方法)。你可以在这里看到几件事。首先,我们@url为此方法提供了多个映射。第二,/$id第一个URL映射有一个奇怪的地方。RestServer将任何:keyword占位符视为URL中的通配符,并将获取URL的该部分并将其传递给方法中具有相同名称的参数。在此示例中,当访问http://www.example.com/users/1234时$id将等于1234.当访问http://www.example.com/users/current时$id将等于null。您的参数的顺序无关紧要,只要它们与占位符(:id$id:username$username)具有相同的名称即可。$id = null当您有多个不需要参数的URL映射时,您还需要确保将参数设置为optional()。否则,您将抛出一个错误,告诉您没有传入必需的参数。

最后要注意的getUser是,此方法只返回一个User对象。这会被序列化为JSON(或可能是XML)并打印出来供应用程序使用。

接下来我们必须saveUser。你在这里看到我们再次有多个URL映射。这次他们还有不同的HTTP方法(POST和PUT)来创建和更新用户。这里的新东西是$data变量。这是一个特殊的关键字参数,它将包含POSTed或PUT到服务器的值。这与常规Web POST不同,它不需要只是名称 - 值对,但可以像JSON一样,发送复杂对象。例如,常规Web POST的主体,比如登录请求,可能如下所示:

username=bob&password=supersecretpassw0rd

但为我们的saveUser方法发布一个新的用户对象可能如下所示

{ “ username ”:“ bob ”,“ password ”:“ supersecretpassword ”,“ firstName ”:“ Bob ”,“ lastName ”:“ Smith ” }

因此,除了常规的Web样式POST之外,您还可以允许POSTING JSON。

最后我们得到listUsers方法。test方法简单。但$query参数是新的。此特殊参数可用于读取查询字符串。并将查询字符串参数保存为关联数组。例如,如果客户端使用url请求此API,/users?search=Manda$query参数将保持[search => Manada]

我称这些类来处理请求Controllers。并且它们可以通过URL映射,数据库配置等完全自包含,这样您就可以毫不费力地将它们放入其他RestServer服务中。

REST index.php

为了让整个服务器启动,你需要创建一个index.php文件,让你的URL重写直接请求(另一个你可以在其他地方学到的主题),然后创建RestServer并添加控制器类到它用于处理。RestServer将使用APC或文件缓存请求之间的URL映射以加速请求。如果使用自动加载和此缓存,则不必在每个请求上加载每个控制器文件,只需要请求所需的文件。缓存仅在生产模式下运行。这是一个示例index.php文件:

spl_autoload_register(); //除非我们使用它们,否则不要加载我们的类

$ mode  =  ' debug ' ; // 'debug'或'production'
$ server = new RestServer($ mode);
// $ server-> refreshCache(); //如果类在生产模式下更改,则暂时取消注释以清除缓存 $ server - > addClass(' TestController ');
$ server - > addClass(' ProductsController ',' / products '); //将此添加为此类中所有URL的基础 $ server - > handle();

而已。您可以根据需要添加任意数量的类。如果存在冲突,则稍后添加的类将覆盖先前添加的重复URL映射。addClass中的第二个参数可以是一个基本URL,它将作为给定类中URL映射的前缀,使您可以更加模块化。

您可以查看RestServer类,复制它并将其用于您自己的目的。它是在MIT许可下。要添加的功能包括XML支持和HTTP身份验证支持。如果您更好地完成此课程,请通过发表评论与大家分享您的更新。我将尝试使用新功能更新此类,因为它们是共享的。我希望你喜欢!

祝你好运,如果你最终使用它,请告诉我!

更新:我为可能需要它的人提供了一个示例.htaccess文件。它只会重写对不存在的文件的请求,因此您可以在webroot中拥有images,css或其他PHP文件,它们仍然有效。任何能给404的东西都会重定向到你的index.php文件。

DirectoryIndex index.php
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^$ index.php [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]
</IfModule>

认证

身份验证对每个应用程序都是唯 但是将身份验证机制绑定到RestServer很容易。只需添加一个名为所有请求的方法authorizeController就会先调用该方法。如果authorize()返回false,则服务器将发出401 Unauthorized响应。如果authorize()返回true,则请求继续调用正确的控制器操作。除非您添加@noAuth操作的文档(我通常将其置于@url映射之上),否则所有操作都将首先运行授权。

在您的身份验证方法中,您可以使用PHP的getallheaders功能或$_COOKIE根据您的用户授权方式。这是您从数据库加载用户对象的位置,并将其设置为$this->user = getUserFromDatabase()以便在以后调用时您的操作可以访问它。

RestServer是一种将应用程序映射到REST API的简单机制。其余细节由您决定。

跨域资源共享

出于安全原因,浏览器限制从脚本内发起的跨源HTTP或REST请求。因此,使用来自浏览器的REST API的Web应用程序只能向其自己的域发出API请求。RestServer通过在REST index.php文件中包含以下代码,可以将覆盖此限制配置为允许交叉请求请求。

/*
* 在$ server = new RestServer($ mode)之后包含以下行;
* 或使用阵列中的多个起点的$服务器- > allowedOrigin = 阵列( ' http://example.com ', ' https://example.com ');
* 或通配符$ server - > allowedOrigin = ' * '
*/
$ server - > useCors = true ; $ server - > allowedOrigin = ' http://example.com ' ;

异常抛出错误处理

您可以通过在类中抛出一个例外来轻松地向API用户提供错误RestException。例

/ **
* 按id或当前用户获取用户
*
* @url GET / users / $ id
* @url GET / users / current
* /
public function getUser( $ id = null) {
if( $ id){
$ user = User :: load( $ id); //可能的用户加载方法
if(!$ user){
throw new RestException(404,' User not found ');
}
} else {
$ user = $ _SESSION [ ' user ' ];
}
return $ user ; //将对象序列化为JSON
};

您可以控制REST服务处理错误的方式。您可以使用添加错误控制器$server->addErrorClass('ErrorController');

此控制器可以定义命名的方法handle401handle404添加您自己的自定义错误处理逻辑。

上一篇:android 52 粘滞广播


下一篇:nginx 正则及rewrite常用规则实例