afilina / phpapifoo
.
Requires
- php: >=5.6
- psr/http-message: ^1.0
Requires (Dev)
- phpunit/phpunit: ^5.0
This package is not auto-updated.
Last update: 2024-09-26 01:00:12 UTC
README
PHP >=5.6
使用此包可以轻松在任何框架中实现RESTful API。目前,仅支持CakePHP 3.2,但我将很快添加其他框架的适配器。
您可以通过Composer安装此文件
composer require afilina/phpapifoo dev-master
这与特定框架的插件有何不同?
想法是让您能够使用您选择的框架。此包不做太多魔法,意味着它仅通过实例化几个类来卸载一些样板代码,但不创建复杂的抽象层。这种方法的目的是降低入门门槛。它还很好地将所有应用程序逻辑保持在您期望的位置,即在控制器和仓库中,而不是在配置文件和监听器中。
示例将说明一切。
这与代码生成器有何不同?
想法是轻松地将功能放入任何代码库中。这对于遗留系统特别有用。您也不必学习任何领域特定语言。您只需要了解PHP和您最喜欢的框架。然而,我相信在利用此库作为所有框架的网关的同时生成REST API代码可能会有价值。
用法
第一步是将请求对象包装在框架的适配器中,例如CakeRequest,然后在ApiRequest中。ApiRequest将提取分页、排序和筛选信息。这就是您通常在控制器中做的事情
$apiRequest = new ApiRequest(new CakeRequest($this->request));
一旦框架实现了他们的请求对象PSR-7,将不再需要CakeRequest
包装器。
第二步是将仓库/表包装在框架的适配器中,例如CakeOrm,然后在ApiRepository中。ApiRepository将根据提供的ApiRequest对象向查询构建器添加部分。这就是您通常在仓库/表中做的事情
$apiRepository = new ApiRepository(new CakeOrm($this));
$results = $apiRepository->getList($query, $apiRequest);
在将查询传递给getList
之前,您可以对查询有完全的控制。您可以挑选列、连接、填充等。您也可以完全控制路由。
getList
方法将遍历请求对象并找到应用于查询的标准。例如,如果它找到GET参数中的title=value,它将尝试在仓库/表中调用addTitleFilter,这就是为什么您将$this
传递给构造函数的原因。
您将过滤和排序方法实现如下
public function addTitleFilter(Query $query, $value)
{
$query->andWhere(['root.title LIKE' => '%'.$value.'%']);
}
public function addTitleSort(Query $query, $order)
{
$query->order('root.title', $order == '-' ? 'DESC' : 'ASC');
}
主别名始终更改为root(至少在这个版本中)。
结果将是一个准备好在控制器中序列化和输出的数组。但是,您也可以在视图中使用这些结果,这使得此包甚至适用于REST API之外的上下文。保持ORM的填充将为您提供模型,因此您可以为标准应用程序重用相同的仓库/表逻辑。
{
"data": [
{
"id": 1,
"title": "Title 1"
},
{
"id": 2,
"title": "Title 2"
}
],
"meta": {
"count": 2,
"pages": 1
}
}
POST、PUT和PATCH操作的输入可以直接由框架验证。
$input = $apiRequest->getBody();
请求格式
/games?title=value&sort=-title&pageSize=10&pageNumber=2
- 使用
sort
与可选的减号(-)以逆序。 - 使用pageSize和pageNumber来控制分页。
- 其他所有查询参数将被解释为筛选。
请记住,sort和filter键名将仅转换为方法名,如addTitleFilter,因此它们独立于数据库模式中的列名。
POST、PUT 和 PATCH 操作的输入应直接在请求体中使用 JSON 提供。
框架示例
CakePHP 3.2
这是一个控制器和表的示例。演示项目:[afilina/cakeapifoo-demo](https://github.com/afilina/cakeapifoo-demo "外部链接")
use Cake\ORM\TableRegistry;
use Cake\Event\Event;
use ApiFoo\Api\ApiRequest;
use ApiFoo\Adapters\Cake\V3_2\CakeRequest;
class GamesController extends AppController
{
public function beforeRender(Event $event)
{
$this->RequestHandler->renderAs($this, 'json');
$this->response->type('application/json');
}
public function getList()
{
$apiRequest = new ApiRequest(new CakeRequest($this->request));
$gamesTable = TableRegistry::get('Games');
$response = $gamesTable->getApiList($apiRequest);
$this->set('response', $response);
$this->set('_serialize', 'response');
}
}
use ApiFoo\Api\ApiRepository;
use ApiFoo\Api\ApiRequest;
use ApiFoo\Adapters\Cake\V3_2\CakeOrm;
class GamesTable extends Table
{
public function getApiList(ApiRequest $apiRequest, $hydrate = false)
{
$this->alias('root');
$query = $this
->find('all')
->hydrate($hydrate)
->select(['root.id', 'root.title'])
;
$apiRepository = new ApiRepository(new CakeOrm($this));
$results = $apiRepository->getList($query, $apiRequest);
return $results;
}
}
使用 $item = $this->newEntity($apiRequest->getBody());
或 $item = $this->patchEntity($item, $apiRequest->getBody());
在 CakePHP 表类 (GamesTable) 中保存实体。
框架会自动处理验证。最简单的方法是在 GamesTable 中创建此方法以添加规则。
use Cake\Validation\Validator;
public function validationDefault(Validator $validator)
{
$validator
->requirePresence('title')
->notEmpty('title', 'Cannot be empty')
->add('title', [
'length' => [
'rule' => ['minLength', 2],
'message' => 'Min 2 characters',
]
])
;
return $validator;
}
贡献
如果您发现更好的方法或添加有用的功能,我欢迎您的 pull requests。文档贡献也受欢迎。
我计划在不久的将来实现 Symfony 和 Laravel 的适配器,以及添加对旧版本框架的支持。我可能需要将适配器拆分为单独的仓库,以避免将所有框架版本依赖项拉入您的项目。
我还希望有一个标准化的错误数组,以处理验证错误,可能使用另一个适配器。