nickrupert/api-wrapper

此软件包已被废弃且不再维护。作者建议使用numenor/api-wrapper软件包。

一个用于快速开发围绕远程API的PHP封装客户端的系统

1.0.0 2021-03-12 22:24 UTC

This package is auto-updated.

Last update: 2021-06-15 15:21:46 UTC


README

简介

API Wrapper是一个用于快速开发围绕远程API的PHP封装客户端的系统。在内部使用Guzzle,此库提供了所有必要的抽象,以快速配置API请求,无需繁琐的样板代码。

要深入了解此库的优点,请查看我们的Medium文章

此README中的所有示例都使用了JSONPlaceholder API,这是一个免费使用的REST API,用于测试基本请求。

安装

要将此库添加到您的项目中,请运行

composer require nickrupert/api-wrapper

用法

路由

基本路由

可以使用Route类创建路由。所有路由方法都接受一个唯一的名称和一个URL。

Route::get('post.all', 'https://jsonplaceholder.typicode.com/posts')

唯一的名称用于引用此路由以进行请求(见请求)。

可用的路由方法

您可以手动声明路由,或使用任何HTTP动词

Route::endpoint('GET', $name, $route);
Route::head($name, $route);
Route::get($name, $route);
Route::post($name, $route);
Route::put($name, $route);
Route::patch($name, $route);
Route::delete($name, $route);
Route::options($name, $route);

每个路由方法都返回一个Endpoint实例,该实例代表您路由的所有配置选项。您可以使用其公共成员方法向端点应用额外的配置选项,例如处理器。

路由组

要将对一组路由应用某些配置选项,请声明一个路由组。路由组可以接受一个基本URL、单个处理器或处理器组(见处理器),以及包含路由声明的回调。路由组可以嵌套,并且所有在其中声明的路由都将接收其所有父组的所有配置选项。

Route::group('https://jsonplaceholder.typicode.com', [], function() {
    Route::get('post.all', 'posts');
});

处理器

创建处理器

Laravel Middleware的启发,Processor类在请求执行前后拦截请求。处理器可以在请求发送之前修改 outgoing 请求,并在返回之前检查和修改响应对象。

处理器是将共享配置选项(如授权头)应用到 outgoing 请求的首选方法(见请求)。

class AuthorizationProcessor extends Processor
{
    public static function handle(Request $request, callable $next): Response
    {
        $request->headers(['Authorization' => 'token']);

        return $next($request);
    }
}

要在请求发送后处理请求的响应,获取由$next回调返回的响应对象(见响应)。

class PostProcessor extends Processor
{
    public static function handle(Request $request, callable $next): Response
    {
        $response = $next($request);
        
        //Do Something
        
        return $response;
    }
}

应用处理器

您可以将处理器应用于路由和路由组。`Route::group` 和 `$endpoint->processor` 函数都可以接受一个数组或单个处理器类名。

Route::group('https://jsonplaceholder.typicode.com', [GroupProcessor::class], function() {
    Route::get('post.all', 'posts')->processor(EndpointProcessor::class);
});

请求

创建请求

在执行 Guzzle 之前,`Request` 类代表 HTTP 请求的完整配置。创建请求的最佳方式是使用静态 `route` 方法,它接受您在声明路由时提供的唯一名称。

$request = Request::route('post.all');

请求路径参数

要设置请求路径参数,您必须在路由上使用花括号 `{}` 声明该参数。

Route::get('post.get', 'posts/{id}');

创建请求时,请使用 `pathParams` 方法设置参数值。

$request->pathParams(['id' => 1]);

此请求将解析为 URL `https://jsonplaceholder.typicode.com/posts/1`。

请求查询参数

要设置请求查询(URL)参数,请使用 `queryParams` 方法。

$request->queryParams(['userId' => 1]);

此请求将解析为 URL `https://jsonplaceholder.typicode.com/posts?userId=1`。

请求正文

根据您的需求,可以使用几种方法之一来设置请求正文。

$request->body('body');
$request->json(['key' => 'value']);
$request->formParams(['key' => 'value']);
$request->multipart(['key' => 'value']);

请求头

要配置请求头,请使用 `headers` 方法,它接受一个包含头名称和值的关联数组。

$request->headers(['Authorization' => 'token']);

认证

要配置由 Guzzle 定义的认证选项(请参阅 Guzzle 文档),而无需手动设置 `Authorization` 头,请使用 `auth` 方法。

$request->auth(['username', 'password']);

选项

要将任何其他配置选项传递给 Guzzle,请使用 `options` 方法。

$request->options(['timeout' => 3.14]);

Guzzle 客户端

要使用自定义 Guzzle 客户端,请将您的自定义实例传递给 `Request::route` 方法。这通常用于调试和测试中的 Guzzle 模拟。

Request::route('post.all', $client);

发送

在配置好所有必要的请求选项后,请使用 `send` 方法执行它以接收响应。

$response = $request->send();

方法链

为了便于使用,所有之前提到的请求方法都可以在单个调用中链接。

$response = Request::route('post.get')
    ->pathParams(['id' => 1])
    ->headers(['Authorization' => 'token'])
    ...
    ->send();

响应

在执行请求后,您将接收到一个 `Response` 对象。此类实现了 `Psr\Http\Message\ResponseInterface`,与直接从 Guzzle 返回的响应对象相同(请参阅 Guzzle 文档),并且实际上将所有接口方法调用转发到 Guzzle 响应对象的实例。然而,此响应对象包含一些额外的用于提高易用性的方法。

获取内容

默认情况下,Guzzle 仅以流的形式返回响应体。虽然可以将它转换为普通的 string 类型,但最好使用 Response 的 getContents 方法。

$body = $response->getContents();

JSON

要自动处理解码 JSON 字符串响应,请使用 json 方法。

$data = $response->json();

默认情况下,此方法将 JSON 字符串解码为关联数组,但若要使用 stdClass 实例代替,请将 false 传递给该方法。

$data = $response->json(false);

资源

Laravel 的 EloquentStripe PHP 库 启发,Resource 类将您的 API 数据表示为具有基本 ORM 类型的模型实例。

对于不适合或不遵循 REST 标准的一些 API,资源可能是不必要的高级抽象。然而,对于处理关系对象数据的 API,资源提供了许多有用的行为。

创建资源

您可以使用自定义的 ApiResource 类来表示您 API 的每个模型。

class Post extends Resource
{
    ...
}

可用的属性方法

与 Eloquent 模型一样,资源维护一个表示模型数据的内部键值对数组,并且有多种方式可以与之交互。

$post = new Post(['id' => 1]);

$post->id = 1;

$id = $post->id;

$post->setAttribute('id', 1);

$id = $post->getAttribute('id');

$post->mergeAttributes(['id' => 1]); //Merge the new attributes into the existing attributes.
                                     //For existing keys, overwrite old values with new, but do not clear other keys.
                                     
$post->setAttributes(['id' => 1]); //Same effect as mergeAttributes.

$post->setAttributes(['id' => 1], true); //Clear all existing attributes.

属性转换

您可以配置 ApiResource 类,在设置属性值时将其转换为其他类型。

可用的转换类型包括

在您的 ApiResource 类中声明属性转换类型。

class Post extends Resource
{
    protected $casts = [
        'id' => 'int',
        ...
    ];
}

请注意,如果远程 API 返回的数据类型正确,声明转换不是必需的。尽管这不会造成任何伤害,但如果不需要转换,则无需声明转换类型。

当设置转换属性时,其值将经过一个内部转换函数的处理,并将其作为正确的类型存储在内部。当您将来检索此对象时,它将返回为存储的类型。

资源转换

要自动将嵌套对象转换为正确的 ApiResource 类,请使用目标类名作为转换类型。当使用数据关联数组设置属性时,它将自动创建目标 Resource 类的实例。

class Post extends Resource
{
    protected $casts = [
        'user' => 'User::class',
        ...
    ];
}

默认操作

默认情况下,此库为您的 ApiResource 类提供基本 CRUD 操作的实现。通过实现相应的接口合约和使用提供的 Traits,将此行为包含在您的类中。

use NickRupert\ApiWrapper\Resource\Contracts\All as AllContract;
use NickRupert\ApiWrapper\Resource\Contracts\Create as CreateContract;
use NickRupert\ApiWrapper\Resource\Contracts\Delete as DeleteContract;
use NickRupert\ApiWrapper\Resource\Contracts\Get as GetContract;
use NickRupert\ApiWrapper\Resource\Contracts\Update as UpdateContract;
use NickRupert\ApiWrapper\Resource\Operations\All;
use NickRupert\ApiWrapper\Resource\Operations\Create;
use NickRupert\ApiWrapper\Resource\Operations\Delete;
use NickRupert\ApiWrapper\Resource\Operations\Get;
use NickRupert\ApiWrapper\Resource\Operations\Update;
use NickRupert\ApiWrapper\Resource\Resource;

class Post extends ApiResource implements AllContract, CreateContract, DeleteContract, GetContract, UpdateContract
{
    use All, Create, Delete, Get, Update;
}

在内部,这些操作映射到上面解释的请求层。要执行查询,请调用可用的操作方法。

$posts = Post::all();           //Queries post.all Route (usually GET)
                                //returns Collection of Post Resources

$post = Post::create([...]);    //Queries post.create Route (usually POST) using provided attributes
                                //returns instance of Post Resource

$post = new Post([...]);
$post->store();                 //Queries post.create Route (usually POST) using current attributes
                                //Fills $post with returned data
                                
Post::delete(1);                //Queries post.delete (usually DELETE) Route with id = 1

$post = new Post(['id' => 1]);
$post->destroy();               //Queries post.delete Route (usually DELETE) with id = 1

$post = Post::get(1);           //Queries post.get Route (usually GET) with id = 1

$post = new Post(['id' => 1]);
$post = $post->fresh();         //Queries post.get Route (usually GET) with id = 1
                                //Returns new instance of Post Resource
                                
$post = new Post(['id' => 1]);
$post->refresh();               //Queries post.get Route (usually GET) with id = 1
                                //Fills $post with returned data
                                
Post::update(1, [...]);         //Queries post.update Route (usually PUT/PATCH) with id = 1 and current attributes

$post = new Post(['id' => 1]);
$post->updateAttributes([...]); //Sets $post attribues using provided attributes
                                //Queries post.update Route (usually PUT/PATCH) with id = 1 and current attributes
                                //Fills $post with returned data
                                
$post = new Post(['id' => 1]);
$post->saveChanges();           //Queries post.update Route (usually PUT/PATCH) with id = 1 and current attributes
                                //Fills $post with returned data

默认操作路由

默认情况下,每个操作都假设了一个特定的路由名称,该名称包括模型名称和操作名称。例如,Post::all 假设的路由名称是 post.all。如果您需要为任何默认操作设置自定义路由名称,请设置您的 ApiResource 类中相关的属性。

class Post extends ApiResource implements AllContract, CreateContract, DeleteContract, GetContract, UpdateContract
{
    use All, Create, Delete, Get, Update;
    
    protected $allRoute = 'customAllRoute';
    protected $createRoute = 'customCreateRoute';
    protected $deleteRoute = 'customDeleteRoute';
    protected $getRoute = 'customGetRoute';
    protected $updateRoute = 'customUpdateRoute';
}

自定义操作

当然,您可以创建满足您API需求的自定义操作。只需定义您需要的函数,并在其中调用 Request::route 方法。或者,如果您需要覆盖默认操作实现的默认行为,您应该自己实现合同方法,而不是引入提供默认行为的特性。