Skip to content

Commit 665220a

Browse files
committed
Add comprehensive documentation for FastForward Container
- Introduced API reference documentation including core concepts, factories, providers, and exceptions. - Added compatibility section detailing runtime compatibility and integration guidance. - Enhanced examples for basic usage, frameworks integration, feature toggles, and testing with providers. - Created FAQ section addressing common questions and best practices for new users. - Expanded getting started guide with installation instructions and a quickstart tutorial. - Updated links section to include dependencies and related standards. - Improved providers documentation with detailed descriptions of built-in providers and their usage. Signed-off-by: Felipe Sayão Lobato Abreu <github@mentordosnerds.com>
1 parent 011f851 commit 665220a

28 files changed

Lines changed: 1112 additions & 251 deletions

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ composer require fast-forward/container
2020

2121
```php
2222
use FastForward\Container\ContainerInterface;
23-
use FastForward\Container\container;
23+
use function FastForward\Container\container;
2424
use FastForward\Config\ArrayConfig;
2525

2626
$config = new ArrayConfig([
@@ -54,6 +54,6 @@ This package is licensed under the MIT License. See the [LICENSE](LICENSE) file
5454
## 🔗 Links
5555

5656
- [Repository](https://github.com/php-fast-forward/container)
57-
- [Packagist](https://packagist.org/packages/php-fast-forward/container)
57+
- [Packagist](https://packagist.org/packages/fast-forward/container)
5858
- [RFC 2119](https://datatracker.ietf.org/doc/html/rfc2119)
5959
- [PSR-11 Container Interface](https://www.php-fig.org/psr/psr-11/)

docs/advanced/container-helper.rst

Lines changed: 56 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,31 @@
11
Container Helper Function
22
========================
33

4-
The ``container()`` helper is the main entry point for building a fully-featured, autowire-enabled container in FastForward Container. It is designed to be flexible and convenient, supporting multiple initialization patterns and advanced composition.
4+
The ``container()`` helper is the main entry point for building a fully-featured,
5+
autowire-enabled container in FastForward Container. It is intentionally flexible so
6+
you can start small and add more sources later.
57

68
Overview
79
--------
810

911
.. code-block:: php
1012
11-
use FastForward\Container\container;
13+
use function FastForward\Container\container;
1214
$container = container($initializer1, $initializer2, ...);
1315
14-
You can pass any combination of the following as arguments:
16+
Supported initializers
17+
----------------------
1518

16-
- **ConfigInterface**: A configuration object (for advanced setups)
17-
- **Psr\Container\ContainerInterface**: Any PSR-11 compatible container
18-
- **ServiceProviderInterface**: Any service provider
19-
- **string**: The fully qualified class name of a ConfigInterface, ServiceProviderInterface, or PSR-11 container (it will be instantiated automatically)
19+
==================================== ================================================================
20+
Initializer Behavior
21+
==================================== ================================================================
22+
``ConfigInterface`` Wrapped in ``ConfigContainer``
23+
``Psr\Container\ContainerInterface`` Added directly to the aggregate
24+
``ServiceProviderInterface`` Wrapped in ``ServiceProviderContainer``
25+
``string`` Instantiated with ``new`` and then resolved using the same rules
26+
==================================== ================================================================
2027

21-
All arguments are optional and variadic. You can mix and match them as needed.
28+
All arguments are optional and variadic. You can mix them freely.
2229

2330
How It Works
2431
------------
@@ -30,18 +37,17 @@ How It Works
3037
- If it's a string, the class is instantiated and then resolved as above.
3138
- Any unsupported type throws an InvalidArgumentException.
3239
2. All resolved containers are appended to an AggregateContainer.
33-
3. If a ConfigContainer is present, it may provide nested initializers (via a special config key), which are also resolved and appended.
40+
3. If a ConfigContainer is present, it may provide nested initializers, which are also resolved and appended.
3441
4. The final result is always an AutowireContainer wrapping the aggregate.
3542

36-
Supported Initializers
37-
----------------------
43+
Resolution order
44+
----------------
3845

39-
- ``ConfigInterface``
40-
- ``Psr\Container\ContainerInterface``
41-
- ``ServiceProviderInterface``
42-
- ``string`` (class name of any of the above)
46+
The aggregate container resolves services from left to right. In practice, this means:
4347

44-
If you pass a string, the function will instantiate the class and treat it as if you had passed the object directly.
48+
- earlier initializers take precedence over later initializers when both can resolve the same ID
49+
- explicit registrations win before autowiring is attempted
50+
- ``container($tests, $defaults)`` is a simple override pattern for tests and local development
4551

4652
Examples
4753
--------
@@ -51,11 +57,12 @@ Basic usage with a service provider:
5157
.. code-block:: php
5258
5359
use FastForward\Container\ServiceProvider\ArrayServiceProvider;
54-
use FastForward\Container\container;
60+
use function FastForward\Container\container;
5561
5662
$provider = new ArrayServiceProvider([
5763
'foo' => fn() => new FooService(),
5864
]);
65+
5966
$container = container($provider);
6067
$foo = $container->get('foo');
6168
@@ -73,53 +80,54 @@ Composing multiple providers and containers:
7380
$containerB = container(ProviderB::class);
7481
$main = container($containerA, $containerB);
7582
76-
Using a config object:
83+
Using a config object with nested providers:
7784

7885
.. code-block:: php
7986
80-
$config = new MyConfig();
87+
use FastForward\Config\ArrayConfig;
88+
use FastForward\Container\ContainerInterface;
89+
use FastForward\Container\ServiceProvider\ArrayServiceProvider;
90+
91+
$config = new ArrayConfig([
92+
'app' => [
93+
'name' => 'FastForward',
94+
],
95+
ContainerInterface::class => [
96+
new ArrayServiceProvider([
97+
Banner::class => static fn($container): Banner => new Banner(
98+
$container->get('config.app.name'),
99+
),
100+
]),
101+
],
102+
]);
103+
81104
$container = container($config);
105+
$banner = $container->get(Banner::class);
82106
83107
Error Handling
84108
--------------
85109

86-
If you pass an unsupported type, or a string that does not correspond to a valid class, the function will throw an InvalidArgumentException.
87-
88-
89-
Advanced: Using Config to Register Providers
90-
--------------------------------------------
110+
If you pass an unsupported value, or a string that does not correspond to a valid class,
111+
the function throws ``InvalidArgumentException``.
91112

92-
If you use a ConfigContainer (from the `fast-forward/config` library), it can provide a special config key (``ConfigContainer::ALIAS.ContainerInterface::class``) containing an array of service providers or containers. The container() helper will automatically resolve and append each of these to the AggregateContainer.
113+
Configuration note
114+
------------------
93115

94-
This allows you to register providers or containers via configuration, making your setup more modular and dynamic.
116+
When you use ``fast-forward/config``, keep this distinction in mind:
95117

96-
Example:
118+
- raw config uses ``FastForward\Container\ContainerInterface::class`` as the key for nested providers
119+
- the wrapped ``ConfigContainer`` exposes normal values through ``config.*`` IDs
97120

98-
.. code-block:: php
99-
100-
use FastForward\Config\ArrayConfig;
101-
use FastForward\Container\ServiceProvider\ArrayServiceProvider;
102-
use FastForward\Container\container;
103-
use FastForward\Container\ContainerInterface;
104-
105-
$config = new ArrayConfig([
106-
ContainerInterface::class => [
107-
new ArrayServiceProvider([
108-
'foo' => fn() => 'bar',
109-
]),
110-
],
111-
]);
112-
113-
$container = container($config);
114-
$foo = $container->get('foo'); // 'bar'
115-
116-
In this example, the config provides the special key for providers (using the fully qualified class name as the key). The container() helper will extract and register all providers listed there, just as if you had passed them directly.
121+
The helper internally asks the ``ConfigContainer`` for
122+
``config.FastForward\Container\ContainerInterface`` and the config container translates that
123+
into the raw config key for you.
117124

118125
Return Value
119126
------------
120127

121-
122-
The function always returns an ``AutowireContainer`` that wraps an ``AggregateContainer`` composed of all resolved sources. This means you get autowiring and aggregation out of the box, regardless of how you initialize the container.
128+
The function always returns an ``AutowireContainer`` that wraps an ``AggregateContainer``
129+
composed of all resolved sources. This gives you autowiring and aggregation out of the box,
130+
regardless of how you initialize the container.
123131

124132
**Autowiring is powered internally by `PHP-DI <https://php-di.org/>`_.**
125133

docs/advanced/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Advanced Topics
44
.. toctree::
55
:maxdepth: 2
66

7+
integrations
78
autowire
89
error-reporting
910
container-helper

docs/advanced/integrations.rst

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,65 @@
11
Integrations
22
============
33

4-
FastForward Container is designed for interoperability with PSR standards and common PHP libraries.
4+
FastForward Container is designed to sit in the middle of an application instead of forcing
5+
you to replace every existing dependency registration approach.
56

6-
- **PSR-11**: ContainerInterface compliance
7-
- **PSR-3**: Logger integration
8-
- **PSR-14**: Event Dispatcher integration
9-
- **PSR-15**: HTTP Middleware integration
7+
PSR-11 containers
8+
-----------------
109

11-
See the ``psr/`` documentation for detailed usage examples for each integration.
10+
Any object implementing ``Psr\Container\ContainerInterface`` can be passed directly to
11+
``container()`` or appended to ``AggregateContainer``.
12+
13+
This is the easiest integration path when:
14+
15+
- your framework already provides a container
16+
- you are gradually migrating from another dependency injection solution
17+
- one subsystem already exposes services through PSR-11
18+
19+
FastForward Config
20+
------------------
21+
22+
If you use ``fast-forward/config``, the package can expose configuration values through
23+
``config.*`` service IDs and can also discover nested providers from the raw config data.
24+
25+
The common pattern is:
26+
27+
1. store nested providers under ``FastForward\Container\ContainerInterface::class`` in the raw config
28+
2. access normal config values at runtime through IDs such as ``config.app.name``
29+
30+
See :doc:`container-helper` for the full flow.
31+
32+
Autowiring with PHP-DI
33+
----------------------
34+
35+
``AutowireContainer`` uses `PHP-DI <https://php-di.org/>`_ internally to instantiate classes
36+
that are not already available through the explicit registrations you provided.
37+
38+
This works best when:
39+
40+
- constructor dependencies are classes or interfaces
41+
- scalar configuration values are supplied through normal provider registrations
42+
- services that need runtime configuration are registered explicitly instead of relying on bare autowiring
43+
44+
Frameworks and application shells
45+
---------------------------------
46+
47+
The package does not require a specific framework. You can use it in:
48+
49+
- console applications
50+
- HTTP applications
51+
- libraries that need an internal composition root
52+
- framework adapters
53+
54+
For concrete examples, see:
55+
56+
- :doc:`../examples/frameworks-slim`
57+
- :doc:`../examples/frameworks-laravel`
58+
59+
Practical advice
60+
----------------
61+
62+
- Keep configured services explicit in providers.
63+
- Let autowiring handle the classes whose dependencies are already known by type.
64+
- Prefer passing existing PSR-11 containers directly instead of wrapping them manually.
65+
- When onboarding new team members, document which services are explicit and which are intentionally autowired.

0 commit comments

Comments
 (0)