Skip to content

improve factories documentation #161

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 2, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions clients/includes/further-reading.inc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
* Use :doc:`plugins </plugins/introduction>` 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 <message-factory>`.
* Learn how you can decouple your code from any PSR-7 implementation by using
the :ref:`HTTP factories <message-factory>`.
2 changes: 1 addition & 1 deletion clients/includes/install-message-factory.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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/message-factory>`. Message factories for
accessed through :ref:`factories <message-factory>`. Message factories for
`Diactoros`_, `Guzzle PSR-7`_ and `Slim Framework`_ are available in the
:doc:`message </message>` component:

Expand Down
2 changes: 1 addition & 1 deletion httplug/library-developers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <message-factory>`.
implementation. Instead, use the :doc:`HTTP factories <../message/message-factory>`.

Discovery
---------
Expand Down
4 changes: 1 addition & 3 deletions message.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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:

151 changes: 117 additions & 34 deletions message/message-factory.rst
Original file line number Diff line number Diff line change
@@ -1,57 +1,140 @@
.. _message-factory:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this file is still named message-factory.rst, which shows in the url. but i think as the package is called message-factory as well, its ok to keep that name.

.. _stream-factory:

Message Factory
===============
HTTP Factories
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although I agree that they are not really Message Factories in most places we refer to them as message factories. The file name also says message-factory, so this could be a little bit confusing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that was the initial question in #141. i find "Message Factory" wrong here. what should we call it? "Message Factories" is wrong, uri and stream are not messages. other ideas? or should i hunt through the doc and change "message factory" to "http factory" where i find that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should i hunt through the doc and change "message factory" to "http factory" where i find that?

I am all for consistency.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i adjusted some of the naming. in many places, we do explicitly mean a message factory and not any http factory.

==============

**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()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You would rarely use the URI Factory since it is required by the message factory.

I suggest removing it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm. i want to show how to create all 3 factories in the example. and i guess there are use cases where you e.g. accept a url string and create the uri from it in your api client to do some uri manipulations before creating the request.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are you ok if we leave this as is?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am fine with that

);

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
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spelling does not like this. is this proper english or not?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually it's latin, but should be ok. Just add it to the spellcheck list.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already see this in english, you can also use "And conversely" if you want, but i think "vice versa" is better.

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

1 change: 1 addition & 0 deletions spelling_word_list.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ sublicense
sync
toolbar
username
versa
whitelist
wiki
Wikipedia
Expand Down