diff --git a/clients/includes/further-reading.inc b/clients/includes/further-reading.inc index 243edb2..b7bd5f8 100644 --- a/clients/includes/further-reading.inc +++ b/clients/includes/further-reading.inc @@ -1,5 +1,5 @@ * Use :doc:`plugins ` to customize the way HTTP requests are sent and responses processed by following redirects, adding Authentication or Cookie headers and more. -* Learn how you can decouple your code from any PSR-7 implementation by using a - :ref:`message factory `. +* Learn how you can decouple your code from any PSR-7 implementation by using + the :ref:`HTTP factories `. diff --git a/clients/includes/install-message-factory.inc b/clients/includes/install-message-factory.inc index 37303cc..22fb8a2 100644 --- a/clients/includes/install-message-factory.inc +++ b/clients/includes/install-message-factory.inc @@ -6,7 +6,7 @@ to install one as well (for example `Guzzle PSR-7`_): $ composer require guzzlehttp/psr7 In order to provide full interoperability, message implementations are -accessed through :doc:`factories `. Message factories for +accessed through :ref:`factories `. Message factories for `Diactoros`_, `Guzzle PSR-7`_ and `Slim Framework`_ are available in the :doc:`message ` component: diff --git a/httplug/library-developers.rst b/httplug/library-developers.rst index 4b3f32d..654406a 100644 --- a/httplug/library-developers.rst +++ b/httplug/library-developers.rst @@ -63,7 +63,7 @@ Messages -------- When you construct HTTP message objects in your library, you should not depend on a concrete PSR-7 message -implementation. Instead, use the :ref:`PHP-HTTP message factory `. +implementation. Instead, use the :doc:`HTTP factories <../message/message-factory>`. Discovery --------- diff --git a/message.rst b/message.rst index 9044d2e..841d3c8 100644 --- a/message.rst +++ b/message.rst @@ -12,7 +12,5 @@ This package contains various PSR-7 tools which might be useful in an HTTP workf * Various Stream encoding tools * Message decorators * Message factory implementations for Guzzle PSR-7, Diactoros and Slim Framework. +* Stream and URI factory implementations for Guzzle PSR-7 and Diactoros * Cookie implementation - -.. _message-factory: - diff --git a/message/message-factory.rst b/message/message-factory.rst index 2cd3f85..1b98a8a 100644 --- a/message/message-factory.rst +++ b/message/message-factory.rst @@ -1,57 +1,140 @@ .. _message-factory: +.. _stream-factory: -Message Factory -=============== +HTTP Factories +============== -**Factory interfaces for PSR-7 HTTP Message.** +**Factory interfaces for PSR-7 HTTP objects.** Rationale --------- -While it should be possible to use every PSR-7 aware HTTP client with any RequestInterface implementation, -creating the request objects will still tie the code to a specific implementation. -If each reusable library is tied to a specific message implementation, -an application could end up installing several message implementations. -The factories abstract away from this. +While it should be possible to use every PSR-7 aware HTTP client with any +request, URI and stream implementation, instantiating objects explicitly would +still tie the code to a specific implementation. If each reusable library is +tied to a specific message implementation, an application could end up +installing several message implementations. The factories move instantiation +out of the library code, further decoupling libraries from implementation. The FIG was pretty straightforward by NOT putting any construction logic into PSR-7. The ``MessageFactory`` aims to provide an easy way to construct messages. -Usage ------ - -.. _stream-factory: +Factories +--------- The `php-http/message-factory` package defines interfaces for PSR-7 factories including: -- ``MessageFactory`` -- ``ServerRequestFactory`` - WIP (PRs welcome) +- ``RequestFactory`` +- ``ResponseFactory`` +- ``MessageFactory`` (combination of request and response factories) - ``StreamFactory`` -- ``UploadedFileFactory`` - WIP (PRs welcome) - ``UriFactory`` -Implementation for the interfaces above for `Diactoros`_ and `Guzzle PSR-7`_ and `Slim Framework`_ can be found in ``php-http/message``. - -.. code:: php +Implementations of the interfaces above for `Diactoros`_, `Guzzle PSR-7`_ and the `Slim Framework`_ can be found in ``php-http/message``. - // Create a PSR-7 request - $factory = new Http\Message\MessageFactory\DiactorosMessageFactory(); - $request = $factory->createRequest('GET', 'http://example.com'); - - // Create a PSR-7 stream - $factory = new Http\Message\StreamFactory\DiactorosStreamFactory(); - $stream = $factory->createStream('stream content'); - -You could also use :doc:`/discovery` to find an installed factory automatically. - -.. code:: php - - // Create a PSR-7 request - $factory = MessageFactoryDiscovery::find(); - $request = $factory->createRequest('GET', 'http://example.com'); +Usage +----- +Instantiate the factories in your bootstrap code or use discovery for them. +Inject the factories into the rest of your code to limit the implementation +choice to the bootstrapping code:: + + // ApiClient.php + + use Http\Message\RequestFactory; + use Http\Message\StreamFactory; + use Http\Message\UriFactory; + + class ApiClient + { + /** + * @var RequestFactory + */ + private $requestFactory; + + /** + * @var StreamFactory + */ + private $streamFactory; + + /** + * @var UriFactory + */ + private $uriFactory; + + public function __construct( + RequestFactory $requestFactory, + StreamFactory $streamFactory, + UriFactory $uriFactory + ) { + $this->requestFactory = $requestFactory; + $this->streamFactory = $streamFactory; + $this->uriFactory = $uriFactory; + } + + public function doStuff() + { + $request = $this->requestFactory->createRequest('GET', 'http://httplug.io'); + $stream = $this->streamFactory->createStream('stream content'); + $uri = $this->UriFactory->createUri('http://httplug.io'); + ... + } + } + +The bootstrapping code could look like this:: + + // bootstrap.php + use Http\Message\MessageFactory\DiactorosMessageFactory; + use Http\Message\StreamFactory\DiactorosStreamFactory; + use Http\Message\UriFactory\DiactorosUriFactory; + + $apiClient = new ApiClient( + new DiactorosMessageFactory(), + new DiactorosStreamFactory(), + new DiactorosUriFactory() + ); + +You could also use :doc:`/discovery` to make the factory arguments optional and +automatically find an available factory in the client:: + + // ApiClient.php + + use Http\Discovery\MessageFactoryDiscovery; + use Http\Discovery\StreamFactoryDiscovery; + use Http\Discovery\UriFactoryDiscovery; + use Http\Message\RequestFactory; + use Http\Message\StreamFactory; + use Http\Message\UriFactory; + + class ApiClient + { + public function __construct( + RequestFactory $requestFactory = null, + StreamFactory $streamFactory = null, + UriFactory $uriFactory = null + ) { + $this->requestFactory = $requestFactory ?: MessageFactoryDiscovery::find(), + $this->streamFactory = $streamFactory ?: StreamFactoryDiscovery::find(); + $this->uriFactory = $uriFactory ?: UriFactoryDiscovery::find();; + } + + ... + } + +.. hint:: + + If you create requests only and no responses, use ``RequestFactory`` in the + type hint, instead of the ``MessageFactory``. And vice versa if you create + responses only. + +Server Side Factories +--------------------- + +It would make sense to also provide factories for the server side constructs +``ServerRequestInterface`` and ``UploadedFileInterface``. We did not get around +to do that yet. Contributions are welcome if you want to define the +``ServerRequestFactory`` and ``UploadedFileFactory``. .. _Diactoros: https://github.com/zendframework/zend-diactoros .. _Guzzle PSR-7: https://github.com/guzzle/psr7 .. _Slim Framework: https://github.com/slimphp/Slim - diff --git a/spelling_word_list.txt b/spelling_word_list.txt index 617f3a2..a1946c1 100644 --- a/spelling_word_list.txt +++ b/spelling_word_list.txt @@ -30,6 +30,7 @@ sublicense sync toolbar username +versa whitelist wiki Wikipedia