update Piwik to version 2.16 (fixes #91)
This commit is contained in:
parent
296343bf3b
commit
d885a4baa9
5833 changed files with 418860 additions and 226988 deletions
259
www/analytics/vendor/container-interop/container-interop/docs/Delegate-lookup-meta.md
vendored
Normal file
259
www/analytics/vendor/container-interop/container-interop/docs/Delegate-lookup-meta.md
vendored
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
Delegate lookup feature Meta Document
|
||||
=====================================
|
||||
|
||||
1. Summary
|
||||
----------
|
||||
|
||||
This document describes the *delegate lookup feature*.
|
||||
Containers are not required to implement this feature to respect the `ContainerInterface`.
|
||||
However, containers implementing this feature will offer a greater lever of interoperability
|
||||
with other containers, allowing multiple containers to share entries in the same application.
|
||||
Implementation of this feature is therefore recommanded.
|
||||
|
||||
2. Why Bother?
|
||||
--------------
|
||||
|
||||
The [`ContainerInterface`](../src/Interop/Container/ContainerInterface.php) ([meta doc](ContainerInterface.md))
|
||||
standardizes how frameworks and libraries make use of a container to obtain objects and parameters.
|
||||
|
||||
By standardizing such a behavior, frameworks and libraries relying on the `ContainerInterface`
|
||||
could work with any compatible container.
|
||||
That would allow end users to choose their own container based on their own preferences.
|
||||
|
||||
The `ContainerInterface` is also enough if we want to have several containers side-by-side in the same
|
||||
application. For instance, this is what the [CompositeContainer](https://github.com/jeremeamia/acclimate-container/blob/master/src/CompositeContainer.php)
|
||||
class of [Acclimate](https://github.com/jeremeamia/acclimate-container) is designed for:
|
||||
|
||||

|
||||
|
||||
However, an instance in container 1 cannot reference an instance in container 2.
|
||||
|
||||
It would be better if an instance of container 1 could reference an instance in container 2,
|
||||
and the opposite should be true.
|
||||
|
||||

|
||||
|
||||
In the sample above, entry 1 in container 1 is referencing entry 3 in container 2.
|
||||
|
||||
3. Scope
|
||||
--------
|
||||
|
||||
### 3.1 Goals
|
||||
|
||||
The goal of the *delegate lookup* feature is to allow several containers to share entries.
|
||||
|
||||
4. Approaches
|
||||
-------------
|
||||
|
||||
### 4.1 Chosen Approach
|
||||
|
||||
Containers implementing this feature can perform dependency lookups in other containers.
|
||||
|
||||
A container implementing this feature:
|
||||
|
||||
- must implement the `ContainerInterface`
|
||||
- must provide a way to register a *delegate container* (using a constructor parameter, or a setter, or any
|
||||
possible way). The *delegate container* must implement the `ContainerInterface`.
|
||||
|
||||
When a *delegate container* is configured on a container:
|
||||
|
||||
- Calls to the `get` method should only return an entry if the entry is part of the container.
|
||||
If the entry is not part of the container, an exception should be thrown (as required in the `ContainerInterface`).
|
||||
- Calls to the `has` method should only return *true* if the entry is part of the container.
|
||||
If the entry is not part of the container, *false* should be returned.
|
||||
- Finally, the important part: if the entry we are fetching has dependencies,
|
||||
**instead** of perfoming the dependency lookup in the container, the lookup is performed on the *delegate container*.
|
||||
|
||||
Important! By default, the lookup should be performed on the delegate container **only**, not on the container itself.
|
||||
|
||||
It is however allowed for containers to provide exception cases for special entries, and a way to lookup into
|
||||
the same container (or another container) instead of the delegate container.
|
||||
|
||||
### 4.2 Typical usage
|
||||
|
||||
The *delegate container* will usually be a composite container. A composite container is a container that
|
||||
contains several other containers. When performing a lookup on a composite container, the inner containers are
|
||||
queried until one container returns an entry.
|
||||
An inner container implementing the *delegate lookup feature* will return entries it contains, but if these
|
||||
entries have dependencies, the dependencies lookup calls will be performed on the composite container, giving
|
||||
a chance to all containers to answer.
|
||||
|
||||
Interestingly enough, the order in which containers are added in the composite container matters. Indeed,
|
||||
the first containers to be added in the composite container can "override" the entries of containers with
|
||||
lower priority.
|
||||
|
||||

|
||||
|
||||
In the example above, "container 2" contains a controller "myController" and the controller is referencing an
|
||||
"entityManager" entry. "Container 1" contains also an entry named "entityManager".
|
||||
Without the *delegate lookup* feature, when requesting the "myController" instance to container 2, it would take
|
||||
in charge the instanciation of both entries.
|
||||
|
||||
However, using the *delegate lookup* feature, here is what happens when we ask the composite controller for the
|
||||
"myController" instance:
|
||||
|
||||
- The composite controller asks container 1 if if contains the "myController" instance. The answer is no.
|
||||
- The composite controller asks container 2 if if contains the "myController" instance. The answer is yes.
|
||||
- The composite controller performs a `get` call on container 2 for the "myController" instance.
|
||||
- Container 2 sees that "myController" has a dependency on "entityManager".
|
||||
- Container 2 delegates the lookup of "entityManager" to the composite controller.
|
||||
- The composite controller asks container 1 if if contains the "entityManager" instance. The answer is yes.
|
||||
- The composite controller performs a `get` call on container 1 for the "entityManager" instance.
|
||||
|
||||
In the end, we get a controller instanciated by container 2 that references an entityManager instanciated
|
||||
by container 1.
|
||||
|
||||
### 4.3 Alternative: the fallback strategy
|
||||
|
||||
The first proposed approach we tried was to perform all the lookups in the "local" container,
|
||||
and if a lookup fails in the container, to use the delegate container. In this scenario, the
|
||||
delegate container is used in "fallback" mode.
|
||||
|
||||
This strategy has been described in @moufmouf blog post: http://mouf-php.com/container-interop-whats-next (solution 1).
|
||||
It was also discussed [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-33570697) and
|
||||
[here](https://github.com/container-interop/container-interop/pull/20#issuecomment-56599631).
|
||||
|
||||
Problems with this strategy:
|
||||
|
||||
- Heavy problem regarding infinite loops
|
||||
- Unable to overload a container entry with the delegate container entry
|
||||
|
||||
### 4.4 Alternative: force implementing an interface
|
||||
|
||||
The first proposed approach was to develop a `ParentAwareContainerInterface` interface.
|
||||
It was proposed here: https://github.com/container-interop/container-interop/pull/8
|
||||
|
||||
The interface would have had the behaviour of the delegate lookup feature but would have forced the addition of
|
||||
a `setParentContainter` method:
|
||||
|
||||
```php
|
||||
interface ParentAwareContainerInterface extends ReadableContainerInterface {
|
||||
/**
|
||||
* Sets the parent container associated to that container. This container will call
|
||||
* the parent container to fetch dependencies.
|
||||
*
|
||||
* @param ContainerInterface $container
|
||||
*/
|
||||
public function setParentContainer(ContainerInterface $container);
|
||||
}
|
||||
```
|
||||
|
||||
The interface idea was first questioned by @Ocramius [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-51721777).
|
||||
@Ocramius expressed the idea that an interface should not contain setters, otherwise, it is forcing implementation
|
||||
details on the class implementing the interface.
|
||||
Then @mnapoli made a proposal for a "convention" [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-51841079),
|
||||
this idea was further discussed until all participants in the discussion agreed to remove the interface idea
|
||||
and replace it with a "standard" feature.
|
||||
|
||||
**Pros:**
|
||||
|
||||
If we had had an interface, we could have delegated the registration of the delegate/composite container to the
|
||||
the delegate/composite container itself.
|
||||
For instance:
|
||||
|
||||
```php
|
||||
$containerA = new ContainerA();
|
||||
$containerB = new ContainerB();
|
||||
|
||||
$compositeContainer = new CompositeContainer([$containerA, $containerB]);
|
||||
|
||||
// The call to 'setParentContainer' is delegated to the CompositeContainer
|
||||
// It is not the responsibility of the user anymore.
|
||||
class CompositeContainer {
|
||||
...
|
||||
|
||||
public function __construct($containers) {
|
||||
foreach ($containers as $container) {
|
||||
if ($container instanceof ParentAwareContainerInterface) {
|
||||
$container->setParentContainer($this);
|
||||
}
|
||||
}
|
||||
...
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
**Cons:**
|
||||
|
||||
Cons have been extensively discussed [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-51721777).
|
||||
Basically, forcing a setter into an interface is a bad idea. Setters are similar to constructor arguments,
|
||||
and it's a bad idea to standardize a constructor: how the delegate container is configured into a container is an implementation detail. This outweights the benefits of the interface.
|
||||
|
||||
### 4.4 Alternative: no exception case for delegate lookups
|
||||
|
||||
Originally, the proposed wording for delegate lookup calls was:
|
||||
|
||||
> Important! The lookup MUST be performed on the delegate container **only**, not on the container itself.
|
||||
|
||||
This was later replaced by:
|
||||
|
||||
> Important! By default, the lookup SHOULD be performed on the delegate container **only**, not on the container itself.
|
||||
>
|
||||
> It is however allowed for containers to provide exception cases for special entries, and a way to lookup
|
||||
> into the same container (or another container) instead of the delegate container.
|
||||
|
||||
Exception cases have been allowed to avoid breaking dependencies with some services that must be provided
|
||||
by the container (on @njasm proposal). This was proposed here: https://github.com/container-interop/container-interop/pull/20#issuecomment-56597235
|
||||
|
||||
### 4.5 Alternative: having one of the containers act as the composite container
|
||||
|
||||
In real-life scenarios, we usually have a big framework (Symfony 2, Zend Framework 2, etc...) and we want to
|
||||
add another DI container to this container. Most of the time, the "big" framework will be responsible for
|
||||
creating the controller's instances, using it's own DI container. Until *container-interop* is fully adopted,
|
||||
the "big" framework will not be aware of the existence of a composite container that it should use instead
|
||||
of its own container.
|
||||
|
||||
For this real-life use cases, @mnapoli and @moufmouf proposed to extend the "big" framework's DI container
|
||||
to make it act as a composite container.
|
||||
|
||||
This has been discussed [here](https://github.com/container-interop/container-interop/pull/8#issuecomment-40367194)
|
||||
and [here](http://mouf-php.com/container-interop-whats-next#solution4).
|
||||
|
||||
This was implemented in Symfony 2 using:
|
||||
|
||||
- [interop.symfony.di](https://github.com/thecodingmachine/interop.symfony.di/tree/v0.1.0)
|
||||
- [framework interop](https://github.com/mnapoli/framework-interop/)
|
||||
|
||||
This was implemented in Silex using:
|
||||
|
||||
- [interop.silex.di](https://github.com/thecodingmachine/interop.silex.di)
|
||||
|
||||
Having a container act as the composite container is not part of the delegate lookup standard because it is
|
||||
simply a temporary design pattern used to make existing frameworks that do not support yet ContainerInterop
|
||||
play nice with other DI containers.
|
||||
|
||||
|
||||
5. Implementations
|
||||
------------------
|
||||
|
||||
The following projects already implement the delegate lookup feature:
|
||||
|
||||
- [Mouf](http://mouf-php.com), through the [`setDelegateLookupContainer` method](https://github.com/thecodingmachine/mouf/blob/2.0/src/Mouf/MoufManager.php#L2120)
|
||||
- [PHP-DI](http://php-di.org/), through the [`$wrapperContainer` parameter of the constructor](https://github.com/mnapoli/PHP-DI/blob/master/src/DI/Container.php#L72)
|
||||
- [pimple-interop](https://github.com/moufmouf/pimple-interop), through the [`$container` parameter of the constructor](https://github.com/moufmouf/pimple-interop/blob/master/src/Interop/Container/Pimple/PimpleInterop.php#L62)
|
||||
|
||||
6. People
|
||||
---------
|
||||
|
||||
Are listed here all people that contributed in the discussions, by alphabetical order:
|
||||
|
||||
- [Alexandru Pătrănescu](https://github.com/drealecs)
|
||||
- [Ben Peachey](https://github.com/potherca)
|
||||
- [David Négrier](https://github.com/moufmouf)
|
||||
- [Jeremy Lindblom](https://github.com/jeremeamia)
|
||||
- [Marco Pivetta](https://github.com/Ocramius)
|
||||
- [Matthieu Napoli](https://github.com/mnapoli)
|
||||
- [Nelson J Morais](https://github.com/njasm)
|
||||
- [Phil Sturgeon](https://github.com/philsturgeon)
|
||||
- [Stephan Hochdörfer](https://github.com/shochdoerfer)
|
||||
|
||||
7. Relevant Links
|
||||
-----------------
|
||||
|
||||
_**Note:** Order descending chronologically._
|
||||
|
||||
- [Pull request on the delegate lookup feature](https://github.com/container-interop/container-interop/pull/20)
|
||||
- [Pull request on the interface idea](https://github.com/container-interop/container-interop/pull/8)
|
||||
- [Original article exposing the delegate lookup idea along many others](http://mouf-php.com/container-interop-whats-next)
|
||||
|
||||
Loading…
Reference in a new issue