Consultant, Formateur, Contributeur.
Un éléphant qui parle HTTP !
Centraliser les appels HTTP de plus en plus présents.
Faciliter les tests et le debug.
Avril 2015 - Premier commit
Octobre 2018 - Version 2.0, compatible PSR18
Novembre 2018 - Sortie de la PSR18
2020 - Intégration de plus en plus répandue
Clients: cURL, socket.
Adapteurs: Guzzle(5/6), Symfony HTTPClient, ReactPHP…
Plugins: Authentification, Log, Cache…
composer require php-http/[client,plugin]
Pourquoi faire simple…
Interopérabilité ?
use Psr\Http\Client\ClientInterface; use Psr\Http\Message\RequestInterface; class MyApiDataRetriever { private $httpClient; public function __construct(ClientInterface $httpClient) { $this->httpClient = $httpClient; } public function retrieveData(RequestInterface $message): AwesomeDTO { return AwesomeDTO::fromResponse( $this->httpClient->sendRequest($message) ); } }
use Psr\Http\Client\ClientInterface; use Psr\Http\Message\RequestInterface; class MyApiDataRetriever { private $httpClient; public function __construct(ClientInterface $httpClient) { $this->httpClient = $httpClient; } public function retrieveData(RequestInterface $message): AwesomeDTO { return AwesomeDTO::fromResponse( $this->httpClient->sendRequest($message) ); } }
use Psr\Http\Client\ClientInterface; use Psr\Http\Message\RequestInterface; class MyApiDataRetriever { private $httpClient; public function __construct(ClientInterface $httpClient) { $this->httpClient = $httpClient; } public function retrieveData(RequestInterface $message): AwesomeDTO { return AwesomeDTO::fromResponse( $this->httpClient->sendRequest($message) ); } }
use Http\Adapter\React\Client; use Laminas\Diactoros\RequestFactory; $client = new Client(/* options */); $dto = (new MyApiDataRetriever($client))->retrieveData( (new RequestFactory)->createRequest('GET', 'http://example.com/api') );
use Http\Adapter\React\Client; use Laminas\Diactoros\RequestFactory; $client = new Client(/* options */); $dto = (new MyApiDataRetriever($client))->retrieveData( (new RequestFactory)->createRequest('GET', 'http://example.com/api') );
use Http\Adapter\React\Client; use Laminas\Diactoros\RequestFactory; $client = new Client(/* options */); $dto = (new MyApiDataRetriever($client))->retrieveData( (new RequestFactory)->createRequest('GET', 'http://example.com/api') );
use Http\Discovery\HttpClientDiscovery; use Http\Discovery\MessageFactoryDiscovery; $client = HttpClientDiscovery::find(); $messageFactory = MessageFactoryDiscovery::find(); $dto = (new MyApiDataRetriever($client))->retrieveData( $messageFactory->createRequest('GET', 'http://example.com/api') );
use Http\Discovery\HttpClientDiscovery; use Http\Discovery\MessageFactoryDiscovery; $client = HttpClientDiscovery::find(); $messageFactory = MessageFactoryDiscovery::find(); $dto = (new MyApiDataRetriever($client))->retrieveData( $messageFactory->createRequest('GET', 'http://example.com/api') );
Séparation des responsabilités (client, messages…),
Définition des prérequis pour chacun de vos objets.
class AwesomeDecorator implements ClientInterface { private $decorated; public function __construct(ClientInterface $client) { $this->decorated = $client; } public function sendRequest(RequestInterface $request): ResponseInterface { /* Vérification ou traitement spécifique */ $response = $this->decorated->sendRequest($request); /* Vérification ou traitement spécifique */ return $response; } }
class AwesomeDecorator implements ClientInterface { private $decorated; public function __construct(ClientInterface $client) { $this->decorated = $client; } public function sendRequest(RequestInterface $request): ResponseInterface { /* Vérification ou traitement spécifique */ $response = $this->decorated->sendRequest($request); /* Vérification ou traitement spécifique */ return $response; } }
class AwesomeDecorator implements ClientInterface { private $decorated; public function __construct(ClientInterface $client) { $this->decorated = $client; } public function sendRequest(RequestInterface $request): ResponseInterface { /* Vérification ou traitement spécifique */ $response = $this->decorated->sendRequest($request); /* Vérification ou traitement spécifique */ return $response; } }
class AwesomeDecorator implements ClientInterface { private $decorated; public function __construct(ClientInterface $client) { $this->decorated = $client; } public function sendRequest(RequestInterface $request): ResponseInterface { /* Vérification ou traitement spécifique */ $response = $this->decorated->sendRequest($request); /* Vérification ou traitement spécifique */ return $response; } }
…dès qu'il y a des tiers.
Psr\Http\Client\ClientInterface
Psr\Http\Message\*
php-http/mock-client
$client = new Http\Mock\Client; $client->on( new RequestMatcher('/api', 'example.com'), function (): ResponseInterface { /* Créer une réponse adaptée */ return $response; } ); $dto = (new MyApiDataRetriever($client))->retrieveData( $messageFactory->createRequest('GET', 'http://example.com/api') );
$client = new Http\Mock\Client; $client->on( new RequestMatcher('/api', 'example.com'), function (): ResponseInterface { /* Créer une réponse adaptée */ return $response; } ); $dto = (new MyApiDataRetriever($client))->retrieveData( $messageFactory->createRequest('GET', 'http://example.com/api') );
$client = new Http\Mock\Client; $client->on( new RequestMatcher('/api', 'example.com'), function (): ResponseInterface { /* Créer une réponse adaptée */ return $response; } ); $dto = (new MyApiDataRetriever($client))->retrieveData( $messageFactory->createRequest('GET', 'http://example.com/api') );
$client = new Http\Mock\Client; $client->on( new RequestMatcher('/api', 'example.com'), function (): ResponseInterface { /* Créer une réponse adaptée */ return $response; } ); $dto = (new MyApiDataRetriever($client))->retrieveData( $messageFactory->createRequest('GET', 'http://example.com/api') );
$client = new Http\Mock\Client; $client->on( new RequestMatcher('/api', 'example.com'), function (): ResponseInterface { /* Créer une réponse adaptée */ return $response; } ); $dto = (new MyApiDataRetriever($client))->retrieveData( $messageFactory->createRequest('GET', 'http://example.com/api') );