Several operations in zend-feed's Reader subcomponent require an HTTP client:
In order to allow developers a choice in HTTP clients, the subcomponent defines several interfaces and classes. Elsewhere in the documentation, we reference where an HTTP client may be used; this document details what constitutes an HTTP client and its behavior, and some of the concrete classes available within the component for implementing this behavior.
First, we define two interfaces for clients,
Zend\Feed\Reader\Http\ClientInterface
and HeaderAwareClientInterface
:
namespace Zend\Feed\Reader\Http;
interface ClientInterface
{
/**
* Make a GET request to a given URL.
*
* @param string $url
* @return ResponseInterface
*/
public function get($url);
}
interface HeaderAwareClientInterface extends ClientInterface
{
/**
* Make a GET request to a given URL.
*
* @param string $url
* @param array $headers
* @return ResponseInterface
*/
public function get($url, array $headers = []);
}
The first is header-agnostic, and assumes that the client will simply perform an
HTTP GET request. The second allows providing headers to the client; typically,
these are used for HTTP caching headers. $headers
must be in the following
structure:
$headers = [
'X-Header-Name' => [
'header',
'values',
],
];
i.e., each key is a header name, and each value is an array of values for that header. If the header represents only a single value, it should be an array with that value:
$headers = [
'Accept' => [ 'application/rss+xml' ],
];
A call to get()
should yield a response.
Responses are modeled using Zend\Feed\Reader\Http\ResponseInterface
and
HeaderAwareResponseInterface
:
namespace Zend\Feed\Reader\Http;
class ResponseInterface
{
/**
* Retrieve the status code.
*
* @return int
*/
public function getStatusCode();
/**
* Retrieve the response body contents.
*
* @return string
*/
public function getBody();
}
class HeaderAwareResponseInterface extends ResponseInterface
{
/**
* Retrieve a named header line.
*
* Retrieve a header by name; all values MUST be concatenated to a single
* line. If no matching header is found, return the $default value.
*
* @param string $name
* @param null|string $default
* @return string
public function getHeaderLine($name, $default = null);
}
Internally, Reader
will typehint against ClientInterface
for the bulk of
operations. In some cases, however, certain capabilities are only possible if
the response can provide headers (e.g., for caching); in such cases, it will
check the instance against HeaderAwareResponseInterface
, and only call
getHeaderLine()
if it matches.
zend-feed ships with a generic ResponseInterface
implementation,
Zend\Feed\Http\Response
. It implements HeaderAwareResponseInterface
, and
defines the following constructor:
namespace Zend\Feed\Reader\Http;
class Response implements HeaderAwareResponseInterface
{
/**
* Constructor
*
* @param int $statusCode Response status code
* @param string $body Response body
* @param array $headers Response headers, if available
*/
public function __construct($statusCode, $body, array $headers = []);
}
PSR-7 defines a set of HTTP message
interfaces, but not a client interface. To facilitate wrapping an HTTP client
that uses PSR-7 messages, we provide Zend\Feed\Reader\Psr7ResponseDecorator
:
namespace Zend\Feed\Reader\Http;
use Psr\Http\Message\ResponseInterface as PsrResponseInterface;
class Psr7ResponseDecorator implements HeaderAwareResponseInterface
{
/**
* @param PsrResponseInterface $response
*/
public function __construct(PsrResponseInterface $response);
/**
* @return PsrResponseInterface
*/
public function getDecoratedResponse();
}
Clients can then take the PSR-7 response they receive, pass it to the decorator, and return the decorator.
To use the PSR-7 response, you will need to add the PSR-7 interfaces to your application, if they are not already installed by the client of your choice:
$ composer require psr/http-message
We also provide a zend-http client decorator,
Zend\Feed\Reader\Http\ZendHttpClientDecorator
:
namespace Zend\Feed\Reader\Http;
use Zend\Http\Client as HttpClient;
class ZendHttpClientDecorator implements HeaderAwareClientInterface
{
/**
* @param HttpClient $client
*/
public function __construct(HttpClient $client);
/**
* @return HttpClient
*/
public function getDecoratedClient();
}
Its get()
implementation returns a Response
instance seeded from the
zend-http response returned, including status, body, and headers.
zend-http is the default implementation assumed by Zend\Feed\Reader\Reader
,
but is not installed by default. You may install it using composer:
$ composer require zendframework/zend-http
By default, Zend\Feed\Reader\Reader
will lazy load a zend-http client. If you
have not installed zend-http, however, PHP will raise an error indicating the
class is not found!
As such, you have two options:
composer require zendframework/zend-http
.Reader
with your own HTTP client.To accomplish the second, you will need an implementation of
Zend\Feed\Reader\Http\ClientInterface
or HeaderAwareClientInterface
, and an
instance of that implementation. Once you do, you can use the static method
setHttpClient()
to inject it.
As an example, let's say you've created a PSR-7-based implementation named
My\Http\Psr7FeedClient
. You could then do the following:
use My\Http\Psr7FeedClient;
use Zend\Feed\Reader\Reader;
Reader::setHttpClient(new Psr7FeedClient());
Your client will then be used for all import()
and findFeedLinks()
operations.