thulium / retrofit-php
Retrofit for PHP - A type-safe PHP REST client
Requires
- php: >=8.2
- guzzlehttp/guzzle: ^7.7
- guzzlehttp/psr7: ^2.5
- letsdrink/ouzo-goodies: dev-master
- nikic/php-parser: ^4.16
- phpdocumentor/reflection-docblock: ^5.3
- psr/http-message: ^2.0
- rawr/t-regx: ^0.41
- symfony/serializer: ^5.4 || ^6.3
Requires (Dev)
- phpunit/phpunit: ^10.2
- symfony/property-access: ^5.4 || ^6.3
- dev-main
- dev-dependabot/github_actions/stefanzweifel/git-auto-commit-action-5.0.1
- dev-dependabot/github_actions/frankdejonge/use-subsplit-publish-1.1.0
- dev-dependabot/github_actions/actions/labeler-5
- dev-feature/add-server-tests
- dev-dependabot/composer/nikic/php-parser-tw-4.16or-tw-5.0
- dev-dependabot/composer/symfony/property-access-tw-5.4or-tw-6.3or-tw-7.0
- dev-dependabot/composer/symfony/serializer-tw-5.4or-tw-6.3or-tw-7.0
This package is not auto-updated.
Last update: 2024-12-10 20:23:06 UTC
README
A type-safe HTTP client for PHP.
This is a PHP port of square/retrofit, under Thulium umbrella.
Installation
Retrofit requires PHP >=8.2
composer require thulium/retrofit-php-core
Please make sure you also install an HTTP client implementation.
HTTP clients:
composer require thulium/retrofit-php-client-guzzle7
To handle more advanced request and responses install a converter.
Converters:
composer require thulium/retrofit-php-converter-symfony-serializer
Introduction
Retrofit turns your PHP interface into an HTTP API.
interface GitHubService { #[GET('/users/{user}/repos')] #[ResponseBody('array', 'Repo')] public function listRepos(#[Path('user')] string $user): Call; }
The Retrofit
class generates an implementation of the GitHubService
interface.
$retrofit = Retrofit::Builder() ->baseUrl('https://api.github.com') ->client(new Guzzle7HttpClient(new Client())) ->addConverterFactory(new SymfonySerializerConverterFactory(new Serializer())) ->build(); $service = $retrofit->create(GitHubService::class);
Each Call
from the created GitHubService
can make a synchronous or asynchronous HTTP request to the remote
webserver.
$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();
Attributes API
Attributes on the interface methods and its parameters indicate how a request will be handled.
Request method
Every method must have an HTTP attribute that provides the request method and path. There are eight built-in
attributes: HTTP
, GET
, POST
, PUT
, PATCH
, DELETE
, OPTIONS
and HEAD
. The path of the resource is specified
in the attribute.
#[GET('/users/list')]
You can also specify query parameters in the URL.
#[GET('/users/list?sort=desc')]
URL manipulation
A request URL can be updated dynamically using replacement blocks and parameters on the method. A replacement block is
an alphanumeric string surrounded by {
and }
. A corresponding parameter must hava attribute #[Path]
using the same
string.
#[GET('/group/{id}/users')] #[ResponseBody('array', 'User')] public function groupList(#[Path('id')] int $groupId): Call;
Query parameters can also be added.
#[GET('/group/{id}/users')] #[ResponseBody('array', 'User')] public function groupList(#[Path('id')] int $groupId, #[Query('sort')] string $sort): Call;
For complex query parameter combinations an array map can be used.
#[GET('/group/{id}/users')] #[ResponseBody('array', 'User')] public function groupList(#[Path('id')] int $groupId, #[QueryMap] string $options): Call;
Request body
An object can be specified for use as an HTTP request body with the #[Body]
attribute.
#[POST('/users/new')] #[ResponseBody('User')] public function createUser(#[Body] User $user): Call;
The object will also be converted using a converter specified on the Retrofit
instance. If no converter is added,
the build-in will be used.
Form-encoded and Multipart
Methods can also be declared to send form-encoded and Multipart data.
Form-encoded data is sent when #[FormUrlEncoded]
is present on the method. Each key-value pair has attribute with
#[Field]
containing the name and the object providing the value.
#[FormUrlEncoded] #[POST('/user/edit')] #[ResponseBody('User')] public function updateUser(#[Field('first_name')] string $first, #[Field('last_name')] string $last): Call;
Multipart requests are used when #[Multipart]
is present on the method. Parts are declared using the #[Part]
attribute.
#[Multipart] #[PUT('/user/photo')] #[ResponseBody('User')] public function updateUser(#[Part] PartInterface $photo, #[Part('description')] string $description): Call;
Multipart parts use one of Retrofit
's converters, or they can implement PartInterface
to handle their own
serialization.
Header manipulation
You can set static headers for a method using the #[Headers]
attribute.
#[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;
A request header can be updated dynamically using the #[Header]
attribute. A corresponding parameter must be provided
to the #[Header]
. If the value is null
, the header will be omitted.
#[GET('/user')] #[ResponseBody('User')] public function getUser(#[Header('Authorization')] string $authorization): Call;
Similar to query parameters, for complex header combinations, an array map can be used.
#[GET('/user')] #[ResponseBody('User')] public function getUser(#[HeaderMap] array $headers): Call;