js361014 / plankton
PHP RESTful API 微框架
Requires
- php: >=7.2.0
- ext-curl: *
- symfony/yaml: ^4.2@dev
README
需求
- PHP >= 7.2
- PHP cURL 扩展
- Apache HTTP 服务器 >= 2.4
- Apache mod_rewrite 已启用
安装
composer require foxdie/rest
目录
客户端
创建客户端
use Plankton\Client\Client; $client = new Client(API_ENDPOINT);
完整示例在这里:https://github.com/foxdie/rest/blob/master/Test/public/simple-client.php
GET 示例
$response = $client->get("/users");
使用回调
$client->get("/users", function(Response $response){ echo $response; });
使用魔法
$response = $client->getUsers();
POST 示例
$response = $client->post("/users", ["email" => "foo@bar.com"]);
使用回调
$client->post("/users", ["email" => "foo@bar.com"], function(Response $response){ echo $response->getLocation(); });
使用魔法
$response = $client->postUsers(["email" => "foo@bar.com"]);
PUT、PATCH 和 DELETE 示例
完整示例在这里:https://github.com/foxdie/rest/blob/master/Test/public/simple-client.php
魔法调用
驼峰命名法
如果你想使用魔法调用,你的路由必须使用驼峰命名法 示例
$client->getUserAccounts()
将匹配以下路由
GET /user-accounts
不支持驼峰命名法和蛇形命名法
示例
内容类型
当你使用魔法调用(例如 $client->postUsers([]);
)或以下方法之一 Client::post()
、Client::put()
、Client::patch()
时,将自动添加 Content-Type
标头。该 Content-Type
将根据您发送到服务器的数据自动猜测
但是,您仍然可以通过自定义请求手动设置 Content-Type
自定义请求示例
use Plankton\Client\Client; use Plankton\Request; $request = new Request(API_ENDPOINT . "/users"); $request ->setMethod(Request::METHOD_POST) ->setParameter("foo", "bar") ->setHeader("User-Agent", "Mozilla/5.0") ->setContentType(Request::CONTENT_TYPE_JSON) ->setData(["email" => "foo@bar.com"]); $client = new Client(API_ENDPOINT); $client->send($request, function(Response $response){ // ... });
自动数据转换
出于可读性考虑,您可以使用 arrays
或 objects
与 Request::setData()
方法一起使用,无论您使用什么内容类型。数据将根据以下规则自动转换
认证策略
匿名认证
$client = new Client(API_ENDPOINT);
基本认证
use Plankton\Client\Strategy\BasicAuthentication; $client = new Client(API_ENDPOINT, new BasicAuthentication(USER, PASSWORD));
客户端凭证
use Plankton\Client\Strategy\ClientCredentialsAuthentication; $client = new Client(API_ENDPOINT, new ClientCredentialsAuthentication( CLIENT_ID, CLIENT_SECRET, AUTHENTICATION_URL ));
授权和访问/刷新令牌请求将自动执行。第 3 个参数是可选的,默认值是 "/token"
服务器
创建服务器
use Plankton\Server\Server; $server = new Server(); $server->run();
完整示例在这里:https://github.com/foxdie/rest/blob/master/Test/public/simple-server.php
创建控制器
您必须创建至少一个扩展 Plankton\Server\Controller 抽象类的控制器
use Plankton\Server\Controller; class APIController extends Controller{ public function getUsers(int $id, Request $request): Response{ } public function postUsers(Request $request): Response{ } }
您的控制器将为您的 API 的每个操作包含一个公共方法
您可以通过两种不同的方式创建路由
- 使用配置文件
- 使用注解
使用配置文件
这将自动禁用注解解析器。路由在 YAML 文件中描述
配置文件示例
routes: get-user: path: /users/{id} method: GET controller: Test\Controller\APIController::getUser create-user: path: /users method: POST controller: Test\Controller\APIController::createUser
完整示例在这里:https://github.com/foxdie/plankton/blob/master/Test/config/server.yml
配置服务器
use Plankton\Server\{Server, Config}; $server = new Server(new Config(CONFIG_PATH));
完整示例在这里:https://github.com/foxdie/plankton/blob/master/Test/public/config-server.php
使用注解
use Plankton\Server\Controller; class APIController extends Controller{ /** * @Route(/users/{id}) * @Method(GET) */ public function getUser(int $id, Request $request): Response{ } /** * @Route(/users) * @Method(POST) */ public function createUser(Request $request): Response{ } }
将根据 @Route 和 @Method 注解自动创建路由
完整示例在这里 : https://github.com/foxdie/rest/blob/master/Test/Controller/APIController.php
@Route 注解
- 接受正则表达式
- 接受占位符:它们将按照它们出现的顺序作为参数传递
- 强烈建议使用脊柱案例
您可以为控制器添加路由前缀
/** * @Route(/users) */ class APIController extends Controller{ /** * @Route(/{id}) * @Method(GET) */ public function getUser(int $id, Request $request): Response{ } /** * @Route(/) * @Method(POST) */ public function createUser(Request $request): Response{ } }
@Method 注解
可能的值包括
- GET
- POST
- PUT
- PATCH
- DELETE
@Exception 注解
class APIController extends Controller{ /** * This will catch any \CustomNameSpace\CustomException * @Exception(CustomNameSpace\CustomException) */ public function catchCustomException(Exception $e, Request $request): Response{ } /** * This will catch all other exceptions * @Exception(*) */ public function catchException(Exception $e, Request $request): Response{ } }
注册控制器
use Plankton\Server\Server; $server = new Server(); $server ->registerController(new APIController()); ->registerController(...); ->run();
完整示例在这里:https://github.com/foxdie/rest/blob/master/Test/public/simple-server.php
创建中间件
(这是可选的)您必须实现 Plankton\Server\Middleware 接口。中间件可以处理传入的请求和输出的响应。
use Plankton\Server\{Request, Response}; use Plankton\Server\{Middleware, RequestDispatcher}; class BasicAuthenticationMiddleware implements Middleware{ public function process(Request $request, RequestDispatcher $dispatcher): Response{ // ... return $dispatcher->process($request); } }
完整示例请参考这里: https://github.com/foxdie/rest/blob/master/Test/Middleware/BasicAuthenticationMiddleware.php
注册中间件
use Plankton\Server\Server; $server = new Server(); $server ->addMiddleware(new BasicAuthenticationMiddleware()) ->addMiddleware(...) ->registerController(new APIController()) ->run();
OAuth2
客户端凭证授权
客户端
use Plankton\Client\Client; use Plankton\Client\Strategy\ClientCredentialsAuthentication; use Plankton\Response; $client = new Client(API_ENDPOINT, new ClientCredentialsAuthentication( CLIENT_ID, CLIENT_SECRET, AUTHENTICATION_URL ));
完整示例请参考这里: https://github.com/foxdie/rest/blob/master/Test/public/oauth2-client.php
服务器
use Plankton\Server\Server; use OAuth2\Middleware\ClientCredentialsMiddleware; use OAuth2\Provider\MemoryProvider; use Test\Controller\APIController; // Access Token provider $provider = new MemoryProvider(); $provider->addClient(CLIENT_ID, CLIENT_SECRET); $server = new Server(); $server ->addMiddleware(new ClientCredentialsMiddleware($provider)) ->registerController(new APIController()) ->run();
完整示例请参考这里: https://github.com/foxdie/rest/blob/master/Test/public/oauth2-server.php
创建自己的访问令牌提供者
您只需实现 AccessTokenProvider 接口
use Plankton\OAuth2\Provider\AccessTokenProvider; use Plankton\OAuth2\Token\{AccessToken, BearerToken}; class PDOProvider implements AccessTokenProvider{ /** * return a new/issued Access Token if you find a client matching the authentication parameters (id + secret) */ public function getAccessToken(string $client_id, string $client_secret): ?AccessToken{ } /** * return a new Access Token if the Refresh Token is valid */ public function refreshToken(string $refreshToken): ?AccessToken{ } /** * authorize or not the given Access Token */ public function isValidAccessToken(string $token): bool{ } }
日志记录
客户端
简单日志记录器
use Plankton\Logging\SimpleLogger; $client->setLogger(new SimpleLogger()); // ... do some requests foreach ($client->getLogger()->getLogs() as $request) { $response = $client->getLogger()->getLogs()[$request]; }
完整示例在这里:https://github.com/foxdie/rest/blob/master/Test/public/simple-client.php
XML 日志记录器
use Plankton\Logging\XMLLogger; $client->setLogger(new XMLLogger()); // ... do some requests header("Content-type: text/xml"); echo $client->getLogger()->getLogs()->asXML();
完整示例请参考这里: https://github.com/foxdie/rest/blob/master/Test/public/oauth2-client.php
自定义日志记录器
您必须实现 Plankton\Request\Logger 接口
use Plankton\{Request,Response}; use Plankton\Request\Logger class CustomLogger implements Logger{ public function log(Request $request, Response $response = NULL): void{ } }
服务器端
您可以通过 添加中间件 来轻松地记录请求和响应
use Plankton\{Request,Response}; use Plankton\Server\{Middleware, RequestDispatcher}; class LogMiddleware implements Middleware{ public function process(Request $request, RequestDispatcher $dispatcher): Response{ $response = $dispatcher->process($request); // log $request and $response here return $response } }
然后注册中间件(#registering-the-middlewares)
use Plankton\Server\Server; use Test\Controller\APIController; use Test\Middleware\LogMiddleware; $server = new Server(); $server ->addMiddleware(new LogMiddleware()) ->registerController(new APIController()) ->run();