afilina/phpapifoo

dev-master / 1.0.x-dev 2016-06-23 15:29 UTC

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 的适配器,以及添加对旧版本框架的支持。我可能需要将适配器拆分为单独的仓库,以避免将所有框架版本依赖项拉入您的项目。

我还希望有一个标准化的错误数组,以处理验证错误,可能使用另一个适配器。