Consumers of libraries using discovery still need to make sure they install one of the implementations.
Discovery can only find installed code, not fetch code from other sources.

Currently available discovery services:

HTTP Client Discovery

HTTP Async Client Discovery

PSR-7 Message Factory Discovery

PSR-7 URI Factory Discovery

PSR-7 Stream Factory Discovery

Mock Client Discovery (not enabled by default)

The principle is always the same: you call the static find method on the discovery service if no explicit
implementation was specified. The discovery service will try to locate a suitable implementation.
If no implementation is found, an Http\Discovery\Exception\NotFoundException is thrown.

New in version 0.9: The exception Http\Discovery\NotFoundException has been moved to Http\Discovery\Exception\NotFoundException.

Discovery is simply a convenience wrapper to statically access clients and factories for when
Dependency Injection is not an option. Discovery is useful in libraries that want to offer
zero-configuration services relying on the virtual packages.

Puli is a first class citizen, but completely optional strategy in discovery.
It provides better flexibility than the built-in strategy, but requires more configuration.

There are two kinds of installation:

In an application

In a reusable library (for development)

In both cases you have to install the discovery package itself and set up Puli.
The easiest way is installing the composer-plugin which automatically configures
all the composer packages to act as Puli modules.

For applications, simply do:

$ composer require puli/composer-plugin

If you need the composer-plugin for development or testing in a reusable library,
make it a development dependency instead:

$ composer require --dev puli/composer-plugin

All of our packages provide Puli resources too, so if Puli is installed, discovery will use it as the primary strategy
and fall back to the built-in list.

If you get an error saying “Could not find resource using any discovery strategy.”
it means that all the discovery strategies have failed.
Most likely, your project is missing the message factories and/or a PRS-7 implementation.
See the user documentation.

If you get an error that says “Puli Factory is not available”, it means that you
have failed to install Puli. Using Puli is optional and you will be able to use
common clients and message factories without Puli (see how).
If you want to use Puli, make sure to install the latest version of
puli/composer-plugin.

The error “No message factories found. To use Guzzle, Diactoros or Slim Framework
factories install php-http/message and the chosen message implementation.” tells
you that no discovery strategy could find an installed implementation of PSR-7
and/or factories for that implementation. You need to install those libraries.
If you want to use Guzzle you may run:

useHttp\Client\HttpClient;useHttp\Discovery\HttpClientDiscovery;classMyClass{/** * @var HttpClient */protected$httpClient;/** * @param HttpClient|null $httpClient Client to do HTTP requests, if not set, auto discovery will be used to find a HTTP client. */publicfunction__construct(HttpClient$httpClient=null){$this->httpClient=$httpClient?:HttpClientDiscovery::find();}}

This type of discovery finds a HTTP asynchronous Client implementation:

useHttp\Client\HttpAsyncClient;useHttp\Discovery\HttpAsyncClientDiscovery;classMyClass{/** * @var HttpAsyncClient */protected$httpAsyncClient;/** * @param HttpAsyncClient|null $httpAsyncClient Client to do HTTP requests, if not set, auto discovery will be used to find an asynchronous client. */publicfunction__construct(HttpAsyncClient$httpAsyncClient=null){$this->httpAsyncClient=$httpAsyncClient?:HttpAsyncClientDiscovery::find();}}

You may find yourself testing parts of your application that are dependent on an
HTTP Client using the Discovery Service, but do not necessarily need to perform
the request nor contain any special configuration. In this case, the
Http\Mock\Client from the php-http/mock-client package is typically used
to fake requests and keep your tests nicely decoupled. However, for the best
stability in a production environment, the mock client is not set to be found
via the Discovery Service. Attempting to run a test which relies on discovery
and uses a mock client will result in an Http\Discovery\Exception\NotFoundException.
Thankfully, Discovery gives us a Mock Client strategy that can be added straight
to the Discovery. Let’s take a look:

In the example of a test class above, we have our MyCustomService which
relies on an HTTP Client implementation. We do not need to test that the actual
request our custom service makes is successful in this test class, so it makes
sense to use the Mock Client. However, we do want to make sure that our
dependency injection using the Discovery service properly works, as this is a
major feature of our service. By calling the HttpClientDiscovery‘s
prependStrategy method and passing in the MockClientStrategy namespace,
we have now added the ability to discover the mock client and our tests will
work as desired.

It is important to note that you must explicitly enable the MockClientStrategy
and that it is not used by the Discovery Service by default. It is simply
provided as a convenient option when writing tests.

Integrating your own implementation with the discovery mechanism using Puli¶

If you use Puli you can easily make your own HTTP Client or Message Factory discoverable:
you have to configure it as a Puli resource (binding in Puli terminology).

A binding must have a type, called binding-type. All of our interfaces are registered as binding types.

For example: a client Http\Client\MyClient should be bind to Http\Client\HttpClient

Puli uses a puli.json file for configuration (placed in the package root).
Use the CLI tool for configuring bindings. It is necessary, because each binding must have a unique identifier.
Read more in Puli’s documentation (Providing Resources).