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')
);