Dev & Ops @Jolicode
<?php
$socket = stream_socket_client('tcp://api.mon-api.com');
fwrite($socket, "GET / HTTP1.1\r\nHost: api.mon-api.com\r\n");
$response = fread($socket, ...);
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://api.mon-api.com');
$response = curl_exec($ch);
<?php
$client = new GuzzleHttp\Client();
$response = $client->request('GET', 'http://api.mon-api.com');
Quelle dépendance choisir ?
composer require stage1/docker-php
composer require aws/aws-sdk-php
Your requirements could not be resolved to an
installable set of packages.
Problem 1
- Conclusion: don't install guzzlehttp/guzzle 6.1.0
- Conclusion: don't install guzzlehttp/guzzle 4.2.3
- Conclusion: don't install guzzlehttp/streams 1.5.1
- Conclusion: don't install guzzlehttp/guzzle 4.2.2
- Conclusion: don't install guzzlehttp/streams 1.5.0
- Conclusion: don't install guzzlehttp/guzzle 6.0.2
- Conclusion: don't install guzzlehttp/guzzle 4.2.1
....
vendor
├── guzzlehttp
│ └── guzzle
├── kriswallsmith
│ └── buzz
├── react
│ └── http-client
├── zendframework
│ └── zend-http
└── zf1
└── zend-http
2 rôles :
Pas votre problème !
Laisser le choix de l'implementation à l'utilisateur final !
<?php
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
interface HttpClient
{
/**
* Sends a PSR-7 request.
*
* @param RequestInterface $request
*
* @return ResponseInterface
*
* @throws Exception
*/
public function sendRequest(RequestInterface $request);
}
<?php
use Psr\Http\Message\RequestInterface;
use Http\Client\Promise;
interface HttpAsyncClient
{
/**
* Sends a PSR-7 request in an asynchronous way.
*
* @param RequestInterface $request
*
* @return Promise
*/
public function sendAsyncRequest(RequestInterface $request);
}
Fonctionnement par callback : onFulfilled / onRejected
<?php
$promise = $httpAsyncClient->sendAsyncRequest($request);
$onFulfilled = function (ResponseInterface $response) {
echo 'The response is available';
return $response;
};
$onRejected = function (Exception $e) {
echo 'An error happens';
throw $e;
};
$promise->then($onFulfilled, $onRejected);
Une Promise renvoie toujours une autre Promise
<?php
$promise
->then($onFulfilled, $onRejected)
->then(...)
;
L'asynchrone en PHP, c'est pas vraiment ça ... (sauf si on utilise React PHP)
La méthode wait permet de forcer l'attente de la résolution de notre requête
<?php
$promise->wait();
"require": {
"php-http/client-implementation": "^1.0"
},
"require": {
"php-http/async-client-implementation": "^1.0"
},
PSR-7 implementations
Ensemble d'interfaces permettant l'abstraction des implémentations PSR-7...
<?php
public function createRequest(
$method,
$uri,
array $headers = [],
$body = null,
$protocolVersion = '1.1'
);
<?php
public function createResponse(
$statusCode = 200,
$reasonPhrase = null,
array $headers = [],
$body = null,
$protocolVersion = '1.1'
);
<?php
/**
* Creates a new PSR-7 stream.
*
* @param string|resource|StreamInterface|null $body
*
* @return StreamInterface
*
* @throws \InvalidArgumentException If the stream body is invalid.
*/
public function createStream($body = null);
<?php
/**
* Creates an PSR-7 URI.
*
* @param mixed $uri
*
* @return UriInterface
*
* @throws \InvalidArgumentException If the URI is invalid.
*/
public function createUri($uri);
Instanciation automatique des clients et factory selon les dépendances présentes
Création d'un client HTTP
<?php
use Http\Discovery\HttpClientDiscovery;
$client = HttpClientDiscovery::find();
Création d'une factory pour créer des requêtes PSR-7
<?php
use Http\Discovery\MessageFactoryDiscovery;
$factory = MessageFactoryDiscovery::find();
$request = $factory->create('GET', 'http://api.mon-api.com/');
composer.json
"require": {
"php-http/client-implementation": "^1.0",
"php-http/discovery": "^0.4@dev"
},
class ClientApi
<?php
class ClientApi
{
public function __construct(
HttpClient $client = null,
MessageFactory $factory = null
)
{
$this->client = $client ?: HttpClientDiscovery::find();
$this->factory = $factory ?: MessageFactoryDiscovery::find();
}
public function getObjects()
{
return $this->client->sendRequest(
$this->messageFactory->create('GET', '/objects')
);
}
}
Couche d'authentification pour les clients
Chargement, Sauvegarde des cookies
Décode le flux d'une réponse HTTP (chunked, gzip, compress, deflate)
Transforme certaines réponses HTTP en Exception (status code 400 à 599)
Log les requêtes, réponses et erreurs sous la norme PSR-3
Suit les redirections d'une réponse HTTP (301, 302, ...)
Réessaye automatiquement l'envoi de la requête en cas d'exception
Calcule le temps d'appel de la requête avec le composant Stopwatch de Symfony
Organisation derrière toutes ces librairies
Jane++