PhpBoot 是一款為快速開發(fā) RESTful API 而設(shè)計(jì)的PHP框架(更多內(nèi)容請(qǐng)前往 PbpBoot Github)崭添。本文為你演示如何使用 PhpBoot 快速開發(fā)一套 RESTful 風(fēng)格的接口厦画。
關(guān)于 RESTful
當(dāng)前 RESTful 已經(jīng)不是新鮮的名詞了,拋開抽象的定義滥朱,我認(rèn)為一個(gè)通俗的解釋可以是:按文件系統(tǒng)的方式去設(shè)計(jì)接口根暑,即把接口提供的功能,當(dāng)做是對(duì)“目錄”的“操作”徙邻。比如一個(gè)登錄接口排嫌,按 RESTful 設(shè)計(jì),可以是POST /tokens/
缰犁,即把登錄淳地,當(dāng)做新建一個(gè)令牌,這里的/tokens/
就是“目錄”帅容,POST
就是對(duì)目錄的“操作”颇象。關(guān)于 RESTful 比較準(zhǔn)確的定義,可以看這里并徘。關(guān)于 RESTful 最佳實(shí)踐遣钳,可以看這里。
示例接口
下面我將演示如何用 PhpBoot 編寫一組“圖書管理”接口麦乞,這些接口包括:
接口名 | METHOD | URI | 請(qǐng)求示例 | 響應(yīng)示例 |
---|---|---|---|---|
查詢圖書 | GET | /books/ | GET /books/?name=php&offset=0&limit=1 | { "total": 0, "data": [ { "id": 0, "name": "string", "brief": "string", "pictures": [ "string" ] } ] } |
獲取圖書詳情 | GET | /books/{id} | GET /books/1 | { "id": 0, "name": "string", "brief": "string", "pictures": [ "string" ] } |
新建圖書 | POST | /books/ | POST /books/ { "id": 0, "name": "string", "brief": "string", "pictures": [ "string" ] } |
123 |
刪除圖書 | DELETE | /books/{id} | DELETE /books/1 |
項(xiàng)目目錄結(jié)構(gòu)
- app
- Controllers
- Books.php 接口實(shí)現(xiàn)
- Entities
- Book.php 數(shù)據(jù)實(shí)體定義
- Controllers
- config
- config.php 配置
- public
- index.php 入口
- vendor 依賴包
入口
index.php 作為項(xiàng)目入口蕴茴, 通常只需要指定配置文件和 Controllers 目錄的路徑即可。最終項(xiàng)目對(duì)外提供的接口姐直, 由不同的 Controllers 的實(shí)現(xiàn)類提供倦淀。
<?php
require __DIR__.'/../vendor/autoload.php';
use PhpBoot\Application;
$app = Application::createByDefault(__DIR__.'/../config/config.php');
//掃描 Controllers 目錄,自動(dòng)加載所有路由
$app->loadRoutesFromPath( __DIR__.'/../App/Controllers', 'App\\Controllers');
//執(zhí)行請(qǐng)求
$app->dispatch();
接口實(shí)現(xiàn)
定義 Book 實(shí)體
為了在不同接口間共享“圖書信息”的數(shù)據(jù)結(jié)構(gòu)声畏,我們定義一個(gè)實(shí)體如下:
class Book
{
/**
* @var int
*/
public $id;
/**
* 書名
* @var string
*/
public $name='';
/**
* 簡(jiǎn)介
* @var string
*/
public $brief='';
/**
* 圖片url
* @var string[]
*/
public $pictures=[];
}
定義 Controller
這里定義了 Books 類作為 Controller撞叽,后續(xù)接口將實(shí)現(xiàn)在此 Books 類中。
/**
* 提供圖書管理接口
* @path /books/
*/
class Books
{
}
上述代碼中的注釋@path /books/
表示 Books 下所有接口插龄,都使用/books/ 作為前綴愿棋。
查詢圖書接口
/**
* 查詢圖書
*
* @route GET /
*
* @param string $name 查找書名
* @param int $offset 結(jié)果集偏移 {@v min:0}
* @param int $limit 返回結(jié)果最大條數(shù) {@v max:1000}
* @param int $total 總條數(shù)
* @throws BadRequestHttpException 參數(shù)錯(cuò)誤
* @return Book[] 圖書列表
*/
public function findBooks($name, &$total, $offset=0, $limit=100)
{
$total = 1;
return [new Book()];
}
為便于理解,這段代碼只是返回了一組固定的數(shù)據(jù)辫狼,真實(shí)場(chǎng)景下應(yīng)該還會(huì)訪問數(shù)據(jù)庫或者緩存初斑。下面將說明這段代碼的工作方式:
@route
定義了此接口的路由,即GET /books/
(加上了@path 定義的前綴)膨处。@param
定義了接口的請(qǐng)求參數(shù)和類型见秤,如果不聲明@param
, 接口參數(shù)將從函數(shù)定義中提取, 如果函數(shù)定義中沒有申明參數(shù)類型真椿,則參數(shù)類型被認(rèn)為是 mixed鹃答。@v
定義了參數(shù)的取值范圍,若不指定突硝,框架將只會(huì)校驗(yàn)請(qǐng)求中的參數(shù)類型测摔, 即如果參數(shù)是類型是 int,則請(qǐng)求中參數(shù)必須是可以轉(zhuǎn)換成 int 的類型,如 123 或者"123"等锋八,否則會(huì)返回 400 錯(cuò)誤函數(shù)的返回值將被 json_encode 后輸出到 body浙于。如果函數(shù)的參數(shù)中沒有引用類型(引用類型的參數(shù)被認(rèn)為是輸出,而不是輸入)挟纱,return 在 json_encode 后即被當(dāng)做 body 輸出羞酗,否則 return 將被賦值給 body 中的 "data"。
-
&$total
是引用類型的參數(shù)紊服,會(huì)被最為輸出檀轨,默認(rèn)輸出到 body 中同名變量中。如這個(gè)接口中欺嗤,最終輸出的 body 形式如下:{ "total": 1, //來自 &$total "data": [ //來自 return { "id": 0, "name": "string", "brief": "string", "pictures": [ "string" ] } ] }
如果希望將 return 輸出到其他位置参萄,或者不使用默認(rèn)的輸入?yún)?shù)綁定方式,可以使用
@bind
, 比如@return Book[] 圖書列表 {@bind response.content.books}
將使 return 結(jié)果綁定在 json 的 "books" 上煎饼,而不是默認(rèn)的 "data"讹挎。$offset=0, $limit=100
定義了默認(rèn)值,如果請(qǐng)求中不包含這些參數(shù)腺占,將使用默認(rèn)值淤袜。注釋
@return Book[]
和@throws BadRequestHttpException
并不會(huì)對(duì)接口的返回有任何影響, 但是會(huì)影響文檔輸出和遠(yuǎn)程調(diào)用(RPC)衰伯。
獲取圖書詳情接口
/**
* 獲取圖書
* @route GET /{id}
*
* @param string $id 指定圖書編號(hào)
*
* @throws NotFoundHttpException 圖書不存在
*
* @return Book 圖書信息
*/
public function getBook($id)
{
return new Book();
}
路由 @route GET /{id}
指定了 url 的 path 有一個(gè)變量{id}
铡羡,變量的值可以通過函數(shù)參數(shù) $id
獲取
新建圖書
/**
* 新建圖書
*
* @route POST /
* @param Book $book {@bind request.request} 這里將post的內(nèi)容綁定到 book 參數(shù)上
* @throws BadRequestHttpException
* @return string 返回新建圖書的編號(hào)
*/
public function createBook(Book $book)
{
return '123';
}
- 請(qǐng)求中的 json 會(huì)被框架自動(dòng)轉(zhuǎn)換成函數(shù)中需要的對(duì)象參數(shù)。
-
{@bind request.request}
表示用請(qǐng)求的 body 構(gòu)造 $book 變量意鲸,若不指定@bind烦周,默認(rèn)是提取請(qǐng)求 body 中 "book" 字段構(gòu)造 $book 變量,也就是說請(qǐng)求會(huì)是以下形式:
{
"book": {
"id": 0,
"name": "string",
"brief": "string",
"pictures": [
"string"
]
}
}
刪除圖書
/**
* 刪除圖書
*
* @route DELETE /{id}
* @param string $id
* @throws NotFoundHttpException 指定圖書不存在
* @return void
*/
public function deleteBook($id)
{
}
如果函數(shù)沒有返回值怎顾,則響應(yīng)的 http body 會(huì)是 void
读慎, 而不是空字符串, 因?yàn)?基于PhpBoot 實(shí)現(xiàn)的接口,默認(rèn)情況下槐雾,http body 總是 json夭委,而空字符串并不是合法的 json。
更多
更多內(nèi)容見:
下期將介紹 PhpBoot 數(shù)據(jù)庫部分的使用株灸,敬請(qǐng)期待。
如需幫助可以聯(lián)系 caoyangmin@gmail.com 擎值,或者加入 QQ 群:185193529