thulium/retrofit-php

Retrofit for PHP - 一个类型安全的PHP REST客户端


README

一个类型安全的PHP HTTP客户端。

这是一个square/retrofit的PHP端口,由Thulium项目组维护。

安装

Retrofit需要PHP >=8.2

composer require thulium/retrofit-php-core

请确保您已安装HTTP客户端实现。

HTTP客户端

composer require thulium/retrofit-php-client-guzzle7

要处理更高级的请求和响应,请安装转换器。

转换器

composer require thulium/retrofit-php-converter-symfony-serializer

简介

Retrofit将您的PHP接口转换为HTTP API。

interface GitHubService
{
    #[GET('/users/{user}/repos')]
    #[ResponseBody('array', 'Repo')]
    public function listRepos(#[Path('user')] string $user): Call;
}

Retrofit类会生成GitHubService接口的实现。

$retrofit = Retrofit::Builder()
    ->baseUrl('https://api.github.com')
    ->client(new Guzzle7HttpClient(new Client()))
    ->addConverterFactory(new SymfonySerializerConverterFactory(new Serializer()))
    ->build();

$service = $retrofit->create(GitHubService::class);

创建的GitHubService中的每个Call都可以向远程服务器发送同步或异步HTTP请求。

$call = $service->listRepos('octocat);

// synchronous request
$call->execute();

// asynchronous request
$callback = new class () implements Callback {
    public function onResponse(Call $call, Response $response): void
    {
    }

    public function onFailure(Call $call, Throwable $t): void
    {
    }
};
$call->enqueue($callback); 
$call->wait();

属性API

接口方法和其参数上的属性指示如何处理请求。

请求方法

每个方法都必须有一个HTTP属性,提供请求方法和路径。有八个内置属性:HTTPGETPOSTPUTPATCHDELETEOPTIONSHEAD。资源路径在属性中指定。

#[GET('/users/list')]

您还可以在URL中指定查询参数。

#[GET('/users/list?sort=desc')]

URL操作

可以使用替换块和方法上的参数动态更新请求URL。替换块是由{}包围的字母数字字符串。相应的参数必须具有使用相同字符串的#[Path]属性。

#[GET('/group/{id}/users')]
#[ResponseBody('array', 'User')]
public function groupList(#[Path('id')] int $groupId): Call;

也可以添加查询参数。

#[GET('/group/{id}/users')]
#[ResponseBody('array', 'User')]
public function groupList(#[Path('id')] int $groupId, #[Query('sort')] string $sort): Call;

对于复杂的查询参数组合,可以使用数组映射。

#[GET('/group/{id}/users')]
#[ResponseBody('array', 'User')]
public function groupList(#[Path('id')] int $groupId, #[QueryMap] string $options): Call;

请求体

可以使用#[Body]属性指定对象作为HTTP请求体。

#[POST('/users/new')]
#[ResponseBody('User')]
public function createUser(#[Body] User $user): Call;

对象还将使用在Retrofit实例上指定的转换器进行转换。如果没有添加转换器,将使用内置的转换器。

表单编码和Multipart

方法也可以声明发送表单编码和Multipart数据。

当方法上有#[FormUrlEncoded]时,发送表单编码数据。每个键值对都有一个包含名称的对象,该对象具有#[Field]属性,包含值。

#[FormUrlEncoded]
#[POST('/user/edit')]
#[ResponseBody('User')]
public function updateUser(#[Field('first_name')] string $first, #[Field('last_name')] string $last): Call;

当方法上有#[Multipart]时,使用Multipart请求。部分使用#[Part]属性声明。

#[Multipart]
#[PUT('/user/photo')]
#[ResponseBody('User')]
public function updateUser(#[Part] PartInterface $photo, #[Part('description')] string $description): Call;

Multipart部分使用Retrofit的某个转换器,或者它们可以实现PartInterface来处理自己的序列化。

头部操作

可以使用#[Headers]属性为方法设置静态头部。

#[Headers(['Cache-Control' => 'max-age=640000')]
#[GET('/widget/list')]
#[ResponseBody('array', 'Widget')]
public function widgetList(): Call;
#[Headers([
    'Accept' => 'application/vnd.github.v3.full+json',
    'User-Agent' => 'Retrofit-Sample-App'
])]
#[GET('/users/{username}')]
#[ResponseBody('User')]
public function getUser(#[Path('username')] string $username): Call;

可以使用#[Header]属性动态更新请求头部。必须提供相应的参数给#[Header]。如果值为null,则将省略该头部。

#[GET('/user')]
#[ResponseBody('User')]
public function getUser(#[Header('Authorization')] string $authorization): Call;

与查询参数类似,对于复杂的头部组合,可以使用数组映射。

#[GET('/user')]
#[ResponseBody('User')]
public function getUser(#[HeaderMap] array $headers): Call;