Proposal for a Container PSR (follow-up: Moving container-interop to PHP-FIG)

1,979 views
Skip to first unread message

David Négrier

unread,
Jun 1, 2015, 9:05:45 AM6/1/15
to php...@googlegroups.com
Hi list!

So PSR-7 being finally accepted, time to focus on other would-be PSRs :)

I proposed in February to move container-interop to the PHP-FIG.
Since then, I have had a chance to talk with a number of PHP community members, and to gather some feedback.

Using this, I wrote a first pre-draft version of a "PSR-Container":

- Container interface
- Meta document

Paul M. Jones agreed to be the coordinator for this PSR and Jeremy Lindblom will act as the second sponsor.

Also, adoption of container-interop has kept improving, with Aura.DI being a fully compatible implementation, and the next release of Slim (the HTTP micro router) being container agnostic, thanks to container-interop.

Finally (although a bit off-topic) I wrote a small article explaining why PSR-7 and PSR-Container are a perfect match for designing framework agnostic modules

I'd be very interested into gathering as much feedback as possible from this pre-draft (although we already gathered a lot), and then, Paul can hopefully open the entrance vote.

Best regards,

David.
Twitter: @david_negrier
Github: @moufmouf

Josh Lockhart

unread,
Jun 1, 2015, 9:13:43 AM6/1/15
to php...@googlegroups.com
I would like to see this happen. You have my support.

--
Josh Lockhart
he...@joshlockhart.com
Web: http://joshlockhart.com
Twitter: https://twitter.com/codeguy
Code: https://github.com/codeguy

On Mon, Jun 1, 2015, at 09:05 AM, David Négrier wrote:
> Hi list!
>
> So PSR-7 being finally accepted, time to focus on other would-be PSRs :)
>
> I proposed in February to move container-interop to the PHP-FIG
> <https://groups.google.com/forum/#!searchin/php-fig/container-interop/php-fig/o_jFaRoLfAo/UBbNznHzp7gJ>
> .
> Since then, I have had a chance to talk with a number of PHP community
> members, and to gather some feedback.
>
> Using this, I wrote a first pre-draft version of a "PSR-Container":
>
> - Container interface
> <https://github.com/container-interop/fig-standards/blob/master/proposed/container.md>
> - Meta document
> <https://github.com/container-interop/fig-standards/blob/master/proposed/container-meta.md>
>
> Paul M. Jones agreed to be the coordinator for this PSR and Jeremy
> Lindblom
> will act as the second sponsor.
>
> Also, adoption of container-interop has kept improving, with Aura.DI
> being
> a fully compatible implementation, and the next release of Slim (the HTTP
> micro router) being container agnostic, thanks to container-interop.
>
> Finally (although a bit off-topic) I wrote a small article explaining why
> PSR-7 and PSR-Container are a perfect match for designing framework
> agnostic modules
> <http://mouf-php.com/psr7-container-interop-equals-cross-framework-module-system>
>
> I'd be very interested into gathering as much feedback as possible from
> this pre-draft (although we already gathered a lot), and then, Paul can
> hopefully open the entrance vote.
>
> Best regards,
>
> David.
> Twitter: @david_negrier
> Github: @moufmouf
>
> --
> You received this message because you are subscribed to the Google Groups
> "PHP Framework Interoperability Group" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to php-fig+u...@googlegroups.com.
> To post to this group, send email to php...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/php-fig/30ab9c36-2f43-409e-8808-1c79f2cb094a%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Matthieu Napoli

unread,
Jun 1, 2015, 10:53:20 AM6/1/15
to php...@googlegroups.com
I'm looking forward to it!

I have played a lot with container-interop from a container point of view (PHP-DI has been compliant for a long time) but also lately from a framework point of view: I was able to add dependency injection support in Silly (micro-framework for CLI) without providing/requiring a container. This was absolutely awesome to do, and it lets users create a CLI application by feeding their own container. And if they want to get started immediately, they can just install the version pre-configured with Pimple or PHP-DI (or whatever other container).

If you want an example on how frameworks can benefit from being container-agnostics, here is the documentation: http://mnapoli.fr/silly/docs/dependency-injection.html If you are interested in how it works you can check out: https://github.com/PHP-DI/Invoker

Paul M. Jones

unread,
Jun 1, 2015, 12:05:46 PM6/1/15
to php...@googlegroups.com
Hi all,

Given the [relevant bylaw](https://github.com/php-fig/fig-standards/blob/master/bylaws/004-psr-workflow.md), this proposal is in pre-draft state right now.

The next step is to announce an entrance vote, which as Coordinator I will do in the very near future.

Thanks to David et al. for putting this together, and for the positive responses thus far.



--
Paul M. Jones
pmjo...@gmail.com
http://paul-m-jones.com

Modernizing Legacy Applications in PHP
https://leanpub.com/mlaphp

Solving the N+1 Problem in PHP
https://leanpub.com/sn1php


Kris Wallsmith

unread,
Jun 1, 2015, 2:38:26 PM6/1/15
to php...@googlegroups.com
I am against standardizing a container interface because we would be implicitly endorsing the use of containers in application code (passing around containers), which is a bad practice. I would rather see FIG create a standard around configuring a container (i.e. Symfony's ContainerBuilder et al), so libraries could ship with one class that would add services to whatever container you are using in your application.

Looking forward to the discussion.

Thanks,
Kris


--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.

Woody Gilk

unread,
Jun 1, 2015, 2:50:10 PM6/1/15
to php...@googlegroups.com
On Mon, Jun 1, 2015 at 1:38 PM, Kris Wallsmith <kris.wa...@gmail.com> wrote:
> I am against standardizing a container interface because we would be
> implicitly endorsing the use of containers in application code (passing
> around containers), which is a bad practice

I've heard this argument before, I would like to see an example of an
application that completely avoids the need to have the container
available in more than one location.

In my experience, container usage typically happens in two places:

1. to bootstrap the application, loading the app framework (routing, etc)
2. to create the responder, loading the controller/domain/worker and
its dependencies

So far, I have been unable to determine how this second step can
eliminated, unless it is assumed that ALL controllers/domains/workers
are created before routing, which is obviously not desirable.

Can you share a real-world example or an article explaining how to
avoid using the container more than once?

Thanks,
--
Woody Gilk
http://about.me/shadowhand

Woody Gilk

unread,
Jun 1, 2015, 2:53:26 PM6/1/15
to php...@googlegroups.com
On Mon, Jun 1, 2015 at 1:49 PM, Woody Gilk <woody...@gmail.com> wrote:
> In my experience, container usage typically happens in two places:

To expand on this point, here are the two usages that we have in Spark:

1. https://github.com/sparkphp/Spark/blob/05a08ef5fa85b9dd699c89de47bb46e46d6cdf58/src/Application.php#L22-L38
2. https://github.com/sparkphp/Spark/blob/05a08ef5fa85b9dd699c89de47bb46e46d6cdf58/src/Router.php#L199-L203

I have not found any reasonable way to remove the second usage.

Paul M. Jones

unread,
Jun 1, 2015, 4:35:21 PM6/1/15
to php...@googlegroups.com
Indeed, even in a trivial case, you still need to retrieve one object from the container to kick off the application, even if it's the last line in a bootstrap script, e.g.:

$front = $container->get('front-controller-service');
$front->run();

David Négrier

unread,
Jun 1, 2015, 5:15:09 PM6/1/15
to php...@googlegroups.com
@Woody: Indeed, most applications will use the container twice: once to bootstrap the application and once to get the controller the router selected.

However, some frameworks simply don't use the container to bootstrap the application (in Symfony, I believe it is the application that is bootstraping the container, the router, and then the router uses the container...)

Furthermore, it would be theoretically possible to use the container only once, if your container supports "lazy loading" of dependencies (PHP-DI and Symfony have such a feature). It allows a container to wrap a dependency in a proxy and to create that dependency only when the proxy is called. Using this technique, you can have a router that points to all controllers and still, not create these controllers until they are indeed needed. Still, I have never seen lazy services used in this scenario so far.

@Kris: We are absolutely not advocating standardizing the service locator pattern! It happens that a service locator and a dependency injection container have the same signature. They are basically the same thing. They only differ by their usage. The interface is not meant to be used by end-users. It is meant to be used by other components, like routers. The Slim microframework, or Silly, the command line is a great example of what can be achieved.

The whole debate of not standardizing the service locator pattern has been extensively discussed when we started container-interop here : https://github.com/container-interop/container-interop/issues/1

You say you would prefer standardizing the way entries are stored into a container. But the truth is that this is very different from one container to another and there is little you can do to standardize this. There are essentially 2 kinds of containers. The ones relying on autowiring (Laravel container is one of those), and the ones relying on configuration (Symfony and Mouf are part of those).

When you use autowiring, in an ideal situation, you do not need any configuration at all, the container will find the dependencies for you. Those containers generally assume that each class is represented by a single instance (the general idea is that those containers store services).

When you use a "configuration based container", the configuration can be highly dependent on the container features. Yml, XML files, pure PHP arrays (Mouf), Closures (like in Pimple), dedicated API... there are many many ways to configure a container. Furthermore, some containers are compiled (Symfony, ZF2) while others are configured at runtime (Laravel, Pimple...).

I believe this is actually a good thing. The way we store things in a container is what makes a container specific. There is absolutely nothing in common between Mouf's UI that lets you drag'n'drop 2 instances together and Pimple that works with closures. And both Mouf and Pimple are perfectly ok. They just share a different philosophy and we should not force a common way to put things in those containers.

Instead, our proposal here is to make the way we use these containers interoperable. This means that in your application, you should be allowed to replace a container by another one. Let's imagine an application with Silex (the microframework). Silex is heavily based on Pimple. What if I could remove Pimple and replace it with another more powerful container as my application is growing and my need for configuration is increasing?

Of course, we know that some frameworks also need to put things in the container (Slim and Silex are using the container to store services at runtime) Since we found it extremely hard to standardize the way things are stored in a container, we worked the other way around the problem. This is the "delegate lookup" part of the spec and it mustn't be overlooked. The whole idea is that you can have several containers in your application working side-by-side. So a framework might need a simple container like Pimple to store the router, and the end-user might use another more powerful container, and still, both containers can be inter-connected.

I hope this relatively short explanation gives you an idea of why we decided to standardize the way things are read from the container rather than the way things are written into it. Do not hesitate to tell me your thoughts about it!

++
David.


--
You received this message because you are subscribed to a topic in the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/php-fig/xC1CCjtyVnw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to php-fig+u...@googlegroups.com.

To post to this group, send email to php...@googlegroups.com.

Anthony Ferrara

unread,
Jun 1, 2015, 5:18:38 PM6/1/15
to php...@googlegroups.com

Woody,

Use a callback. As in a function.

You the have a file of route handlers, which incidentally are basically identical to your controller anyway. Or if you want more organization, organize the functions in multiple files. The question that it raises is why do controllers need to be objects, if you are never using them polymorphically.

Anthony

Woody Gilk

unread,
Jun 1, 2015, 5:40:10 PM6/1/15
to php...@googlegroups.com
On Mon, Jun 1, 2015 at 4:18 PM, Anthony Ferrara <ircm...@gmail.com> wrote:
>> I have not found any reasonable way to remove the second usage.
>
> Use a callback. As in a function.
>
> You the have a file of route handlers, which incidentally are basically
> identical to your controller anyway. Or if you want more organization,
> organize the functions in multiple files. The question that it raises is why
> do controllers need to be objects, if you are never using them
> polymorphically.

Actually my routing looks a lot more like a hash map than anything else:

GET /users/{id} => Example\Domain\GetUserById

This translates very well to autoloading, without any custom stuff to
autoload closures (I assume you meant closure and not function, since
this is 2015).

The domain is constructed with all collaborators by the DI container
and can be easily correlated with its associated test, because the
test is called GetUserByIdTest.

I don't see how any of this would be improved by using a closure, or
how it would eliminate the second DI usage. Could you please explain
it more throughly?

Paul M. Jones

unread,
Jun 1, 2015, 7:59:31 PM6/1/15
to php...@googlegroups.com

> On Jun 1, 2015, at 13:38, Kris Wallsmith <kris.wa...@gmail.com> wrote:
>
> I am against standardizing a container interface because we would be implicitly endorsing the use of containers in application code (passing around containers), which is a bad practice.

I agree that it's a bad practice, but I disagree that specifying a ContainerInterface::has()/get() implicitly endorses that practice. The Aura.Di 3.x Container, for example, implements the interface, and is explicitly not to be used as a Service Locator.


> I would rather see FIG create a standard around configuring a container (i.e. Symfony's ContainerBuilder et al), so libraries could ship with one class that would add services to whatever container you are using in your application.

That may arise out of this discussion, although I will opine it would be a much more complex topic. Even so, there will need to be a way for those configuration systems to check for the existence of, and then retrieve, existing service objects, so has() and get() will still be necessary.

On the whole, I think David et al. have already done a very good job of vetting and limiting their offering here, which is one reason I've volunteered as Coordinator.

Marco Pivetta

unread,
Jun 2, 2015, 4:34:12 AM6/2/15
to php...@googlegroups.com
Just a note to those worried about "OH EM GEE, THEY ARE STANDARDIZING A SERVICE LOCATOR! I CANNOT LOOK AT THAT WITHOUT WASHING MY EYES!":

 - this is an interop-library
 - it is meant to make multiple containers talk to each other
 - the only possible "glue" interface for DICs (discovered) so far is this one
 - it does in no way suggest that end users should use the service locator directly
 - even if users want to use the SL directly, relying on this abstraction is still better than relying on a lib-specific SL

We've beaten this to death while speccing it out: https://github.com/container-interop/container-interop/issues

Márk Sági-Kazár

unread,
Jun 2, 2015, 6:08:48 AM6/2/15
to php...@googlegroups.com
Hey,

I've been watching this for a long time, glad it is moving forward.

Since it exists for a long time now, I hope/guess it is going to be finished relatively faster than PSR-7. ;)

Cheers,
Mark

Kris Wallsmith

unread,
Jun 2, 2015, 1:28:22 PM6/2/15
to php...@googlegroups.com
Are there any examples of libraries other than containers using the interop container interface? I'm still not seeing how this goes toward interoperability. I understand the concept of container delegation, but what exactly is the vision? Are we suggesting libraries "export" containers with services from the library? What exactly is the problem we are solving?

Thanks again,
Kris


--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.

To post to this group, send email to php...@googlegroups.com.

Paul M. Jones

unread,
Jun 2, 2015, 1:41:27 PM6/2/15
to php...@googlegroups.com

> On Jun 2, 2015, at 12:28, Kris Wallsmith <kris.wa...@gmail.com> wrote:
>
> What exactly is the problem we are solving?

I believe the meta-document attempts to answer that and other questions:

https://github.com/container-interop/fig-standards/blob/master/proposed/container-meta.md

Matthieu Napoli

unread,
Jun 2, 2015, 2:17:37 PM6/2/15
to php...@googlegroups.com
Additionally to Paul's answer, Kris please take the time to read what has already been posted in this thread (e.g. for your question "Are there any examples of libraries other than containers using the interop container interface?").

Matthieu

Jan Jakeš

unread,
Jun 3, 2015, 3:47:24 AM6/3/15
to php...@googlegroups.com
Hi all,

following the PSR-7 process I started to think that the FIG group has already matured but when I read this PSR and realized that it is real joke I was shocked. It's not that it would be messy or badly prepared, the job is done well, but the problem is that it shows how badly people tend to understand the concept of DI. Even worse - it shows that even the people from FIG doesn't seem to understand the DI which is really alarming - it basically show the PHP community is in the hands of immature self-proclaimed "PHP FIG" group.

Now, don't get me wrong, even if some of the standards had some controversy in them, it's great to actually have the standards (PSR-0, PSR-1, PSR-2, PSR-4, PSR-7) and I really appreciate the work and the fact the you guys did it. And even if I would do some things differently the main point is the fact we have the standards. PSR-7 for instance will open a new era of framework interoperability.

Having said that and looking at the other PSRs, there is absolutely no place among these standards for what you call "PSR-Container". There are very serious issues with this PSR and I'll try to explain why:

First and the most obvious reason - the meta document says "By standardizing the way entries are fetched from a container, frameworks and libraries using the Container PSR could work with any compatible container." Now, if we are talking about DI, I say just "what?" What entries fetching? Why on earth should this be standardized? There's apparently a huge misunderstanding among the people who prepared this what DI actually is. The point of DI container is not that you use it to fetch services everywhere and thus you need an interface to that (that would be a simple global service locator) - the main point of a correctly used DI container is that your application actually doesn't even know that it exists!

Now, this is extremely important - a well-designed application knows nothing about the DI container, in fact you only need to configure it and fetch one service in your bootstrap script. For instance $container->getByType(Symfony\Component\Console\Application::class)->run() or $container->getByType(Nette\Application\Application::class)->run(), etc. Now, do we really need a standard for fetching one service? Of course not, but there's more...

I used the getByType method on purpose since the best DI containers I know use autowiring (many "DI" containers aren't even a real DI). The authors of this PSR probably think they didn't forget about autowiring since they mention "the identifier is the class name, or an interface name (used mostly by frameworks with an autowiring capability)" - well, that's wrong. Autowiring is a great feature of DI containers but it doesn't replace service names. Why? Because not everything should be autowired. Typically, if you have more instances of the same interface (and that's really not uncommon) you may autowire only one of them and reference the rest by names. Sure, you usually do the references only inside the configuration file, because at the end you can fetch just one service, but that doesn't vindicate the correctness of the interface you've proposed.

And now coming to the big hype called container interoperability - I've seen you use this as a (wrong) excuse any time somebody points out this PSR is wrong or that it has nothing to do with DI. The response (excuse) in the discussions usually was "it's actually not for a container but for container interoperability" - huh? I guess you can't be more wrong. So you are saying you want us to use 5 different containers in your application and connect them by your fantastic interface? Is it really possible that somebody can even mean this seriously? I'll try to explain what's the problem:

The future of all the PHP packages that are getting really great lately is that they will be (or are) usable in basically any framework and the best way (not the only way) to get them to your framework is a good DI. Eventually, the DI will be the only package that will be specific for your "framework" - this basically means that there will be no framework, but rather many small packages - and we already see that happening. Every programmer will chose his DI implementation and a set of packages and configure them with that DI. Simplified, that's the general view. Now, can anybody tell my why would I need the container to have a standard interface and why would I need more containers connected together? Do you realize that a great container with autowiring-resolving capabilities simply cannot interoperate with another one that doesn't have these capabilities? You add a service to your config file that is registered in the second-non-autowiring container and you expect your great container to autowire any services that are in your container and at the same time in your class' constructor and... it simply won't happen. And no ContainerInterface can ever save that.

---
To sum it up:
  1. We don't need ContainerInterface for fetching services because the correct way is not knowing about it in the code (except fetching one service in bootstrap).
  2. You can't mix autowiring and fetching by service names in the same method. Doing so is a misunderstanding of basic autowiring principles.
  3. Container interoperability is a wrong pattern and it cannot be used among containers with different capabilities (the problem is especially autowiring).
  4. You seem to think that a simple global service locator is the same as DI Container. The interface you've proposed and the interoperability you are talking about would work in the case of service locator.
Some applications can use DI, some applications service locator, some applications singleton environment, some static environment... and there are tons of other configuration options. Therefore, there MUST NOT be a standard for that because it is simply not possible to standardize such a thing.

Btw. Kris had really good points and questions and non of you was able to answer it. Please, answer to his questions and think about them. Responses like "read the meta document" are just arrogant and show you don't want to think about this PSR yourselves. I totally agree with Kris that standardizing a way of actually configuring a container would be much more useful (althougth probably hard to do).

In the end I would again than the FIG group for all other hard work and ask - please take these serious issues into consideration and don't smash me with a "you didn't read..." - I did and I say it's wrong in many ways.

(PS: Checking Twitter it seems I'm not the only one who have noticed this PSR is a big misunderstanding of DI Container vs. Service Locator.)

Thanks,
Jan




Dne pondělí 1. června 2015 15:05:45 UTC+2 David Négrier napsal(a):

Marco Pivetta

unread,
Jun 3, 2015, 4:08:39 AM6/3/15
to php...@googlegroups.com

@Jan this is standardizing a locator, not an injector: you are missing the point, and you didn't read the thread.

--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.

Olivier Laviale

unread,
Jun 3, 2015, 4:17:34 AM6/3/15
to php...@googlegroups.com
Hi,

Are you sure about the "Interface" in the interface class name? I mean, there is no ArrayAccessInterface as far as I know.

Jan Jakeš

unread,
Jun 3, 2015, 4:17:37 AM6/3/15
to php...@googlegroups.com
@Marco: I know that it is standardizing the "locator", I've read the thread, I didin't miss the point and I made many points about serious concerns of this PSR.

Either you didn't read what I said or you just completely ingore it.
(I was kind of expecting it - that's why I said "please take these serious issues into consideration and don't smash me with a "you didn't read..." - I did and I say it's wrong in many ways." in the first place.)

Now would you be so kind to read at leas the four points in the "To sum it up" section?

Thanks,
Jan

Dne pondělí 1. června 2015 15:05:45 UTC+2 David Négrier napsal(a):
Hi list!

Stephan Hochdörfer

unread,
Jun 3, 2015, 4:20:05 AM6/3/15
to php...@googlegroups.com
If I recall correctly I tried this some years ago and most framework authors told me that their framework is using the configuration in a very specific way which would not allow a standardization. You probably find the discussion in the archives of this group. I am absolutely with you that this would be the "best way"(tm) to drive things forward, the general idea of this PSR is to go an easy route and provide an standardized interface so that you can "connect" the containers from different packages in one and not care about which config format is used for the different containers.

Stephan Hochdörfer

Matthieu Napoli

unread,
Jun 3, 2015, 4:28:43 AM6/3/15
to php...@googlegroups.com
Jan,

Yes this is all explained either in this thread or the meta document. To prove that, I'll take your first point and show you that it was all already discussed and answered:

  1. We don't need ContainerInterface for fetching services because the correct way is not knowing about it in the code (except fetching one service in bootstrap).
You answered your own point yourself in this very sentence… As it has been said already in this thread, an application needs to initialize itself (e.g. get the application object from the container) and *usually* get the controller initialized with its dependencies (get the controller from the container after the routing has been done). So YES, it's OK for an application to call a container. Else you don't need to install a container if you don't use it.

So this is by no mean about encouraging users to use containers as service locators (but hey, it has only been said 5 times in this thread).

This is about letting users choose their container based on their needs. I am going to link again to one of my project, but this is to prove to you that it is possible: http://mnapoli.fr/silly/docs/dependency-injection.html In Silly you can provide the container you want. Want a simple and easy API -> use Pimple. Want to scale to a larger app -> use X/Y/Z…

Does that mean that user code will call Pimple/X/Y/Z? No.
That means that the framework/application will use the container to get the controllers without being coupled to said container (i.e. without knowing which implementation is used).

Hopefully this helps.

Jan Jakeš

unread,
Jun 3, 2015, 4:51:39 AM6/3/15
to php...@googlegroups.com
Thanks, Matthieu. I would appreciate responding also to my other points if you have 5 minutes. This is not a preference-dispute, this is a discussion about a standard. Saying "we still can have interface for that even if we want to call it only once" is obviously the easiest response on the issues I've addressed. (Btw. nobody responded to Kris either.)

Now, looking at http://mnapoli.fr/silly/docs/dependency-injection.html, why do you use $app->useContainer($container); and $app->command('greet [name]', 'the-service-id'); instead of:

$app->addCommand('greet [name]', $container->getService('the-service-id'));

or 

$app->addCommand('greet [name]', $container->getByType('MyApp\Command\ScanCommand'));

Notice that in the second case your app needs no knowledge about the container and the container needs no ContainerInterface. Also, you can fetch all the comment just by the fact that they implement the same command interface (good container can do it) and even better solution would be to write a compiler extension that would add the commands during compilation. Also - your approach does exactly what I said - it uses the container as a service locator (this confirms that the you guys really don't get the DI concept). The most correct way in DI would be to fetch just your console application from the container, already configured.

Hope you understand my points and why your example still doesn't authorize the ContainerInterface.

Jan



Dne pondělí 1. června 2015 15:05:45 UTC+2 David Négrier napsal(a):
Hi list!

Benjamin Eberlei

unread,
Jun 3, 2015, 5:08:28 AM6/3/15
to php...@googlegroups.com
On Wed, Jun 3, 2015 at 10:17 AM, Jan Jakeš <j...@jakes.pro> wrote:
@Marco: I know that it is standardizing the "locator", I've read the thread, I didin't miss the point and I made many points about serious concerns of this PSR.

To be honest, the first paragraphs are pretty harsh and I didnt continue reading your post because of that. This list is high volume, so everyone needs to filter - if a mail starts like yours, then 90% of people will not continue reading it, because it triggers the trolling alarm.

The FIG is about interop between frameworks, It has nothing to do with userland or developers using those frameworks. Between libraries and frameworks, a container standard is very important. My usual application at the moment has 3 different DI container in them because third party libraries use them and then you cannot share resources between them (everybody has its own logger again).

--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.

Jan Jakeš

unread,
Jun 3, 2015, 5:22:22 AM6/3/15
to php...@googlegroups.com
Benjamin: It's really sad that one expresses his opinions to the PSR guys and two of them smash it down without reading and one answers just the first question. People who define standards shouldn't act like that.

If I started harsh, please try to skip the first part and get to the main points at the end. I really want to avoid trolling but written communication is always kind of hard.

Thanks,
Jan


Dne pondělí 1. června 2015 15:05:45 UTC+2 David Négrier napsal(a):
Hi list!

Christopher Pitt

unread,
Jun 3, 2015, 7:09:17 AM6/3/15
to php...@googlegroups.com
Jan, it takes 0 effort not to be a jerk. There are polite, tone-neutral and jerky ways to say things. Some examples of jerky tone:
  • "it is real joke"
  • "the PHP community is in the hands of immature self-proclaimed "PHP FIG" group"
  • "now coming to the big hype called container interoperability - I've seen you use this as a (wrong) excuse any time"
  • "I guess you can't be more wrong."
  • "are just arrogant and show you don't want to think about this PSR yourselves"
    All of your thoughts can be re-phrased, in kind and polite ways. You may not care about the impact careless words have on everyone else, but the impact will not help sway anyone to your way of thinking. Want people to answer your questions? Ask them without the "fuck you's".

    --
    1. We don't need ContainerInterface for fetching services because the correct way is not knowing about it in the code (except fetching one service in bootstrap).
    1. Someone has to bootstrap. That seems to be agreed upon. It doesn't mean that the application or libraries you use need to know about the container beyond the bootstrap phase. Autowiring is great. 
    1. You can't mix autowiring and fetching by service names in the same method. Doing so is a misunderstanding of basic autowiring principles.
    1. You can. Laravel is a great example of this working. Many objects are resolved by service name. Many are resolved by class names. A great majority are resolved by autowiring.
    1. Container interoperability is a wrong pattern and it cannot be used among containers with different capabilities (the problem is especially autowiring).
    1. All containers (whether they support autowiring or not) should be able to resolve an object. If that's all these interfaces seek to standardise then I don't see why this is a problem. I mean, it's basically saying; "if you can resolve, then resolve like this or you don't conform to the PSR". Perhaps I'm missing your intent with this.
    1. You seem to think that a simple global service locator is the same as DI Container. The interface you've proposed and the interoperability you are talking about would work in the case of service locator.
    1. Perhaps you can clarify how you came to think this? With a quote or something.
    Hopefully we can advance the conversation in a civil manner, from here on...

    Jan Jakeš

    unread,
    Jun 3, 2015, 8:21:30 AM6/3/15
    to php...@googlegroups.com
    Christopher: You seem to be right about the tone of some of my quotes, I'll pay attention to avoid that next time. I'll try to respond to your points:

    1. We don't need ContainerInterface for fetching services because the correct way is not knowing about it in the code (except fetching one service in bootstrap).
      Someone has to bootstrap. That seems to be agreed upon. It doesn't mean that the application or libraries you use need to know about the container beyond the bootstrap phase. Autowiring is great.
    1. You are right that the existence of ContainerInterface won't make it harder to use DI in a clear way. I want to point more to my doubts that this interface is necessary (see more below).

    1. You can't mix autowiring and fetching by service names in the same method. Doing so is a misunderstanding of basic autowiring principles.
      You can. Laravel is a great example of this working. Many objects are resolved by service name. Many are resolved by class names. A great majority are resolved by autowiring.
    1. You can in a particular implementation. But there are DI's that implement both with different methods - sure, we can say that you can always put it to a single method and prioritize types over names or the other way round, but - isn't that already a sign that the interface won't be universal enough? This is really more of a question - I am not sure, maybe you've convinced me that a single get might work...

    1. Container interoperability is a wrong pattern and it cannot be used among containers with different capabilities (the problem is especially autowiring).
      All containers (whether they support autowiring or not) should be able to resolve an object. If that's all these interfaces seek to standardise then I don't see why this is a problem. I mean, it's basically saying; "if you can resolve, then resolve like this or you don't conform to the PSR". Perhaps I'm missing your intent with this.
    1. I think (and I'll sum this up below) that the biggest problem and from my point of view a "DI antipattern" is to use multiple containers at all. What I wanted to say in particular is that if one container wants to autowire a parameter to a constructor of some service (by type) and this container uses another container (that can reslove the service for the parameter) over the interface - in case when the second container is not able to fetch a service by type, this autowiring resolution in the first container will fail, won't it?

    1. You seem to think that a simple global service locator is the same as DI Container. The interface you've proposed and the interoperability you are talking about would work in the case of service locator.
      Perhaps you can clarify how you came to think this? With a quote or something.
    1. Because if we speak of clean and correct DI, then (in my opinion) nothing should depend on a DI container (no packages, libs, apps, etc.) - ideally just the bootstraping part. And if nothing depends on that, we need no interface. On the other hand a service locator works this way - objects need it as a dependence and we query objects exactly as described by the ContainerInterface. Also, it would work exactly the way described in the PSR to communicate with other service locators. That's why it seems so to me. (To clarify my terminology - when you have a Symfony controller for instance and you call in it $container->getService('xxx') then you are service-locating, but when you get the service 'xxx' through a normal constructor parameter, then we speak of DI.)
    So in addition to 1, 3, and 4 - I think libraries shouldn't have their DI's or depend on them, I consider that a DI antipattern and a step backwards in direction of a service locator. There should always be just a single DI container same way as there is probably a single router in a an application. Depending on a DI container anywhere is against DI. I've read all the arguments but none of them convinced me that we need to connect multiple containers together. That's just one way how to deal with configuration and since it was introduced by container-interop it's probably also quite a used way nowadays, but that doesn't make it the correct way. What Matthieu sent to me as an example is for me an antipattern. I say again: Nothing should depend on a DI container because then it becomes a service locator.

    Hope this clears my thoughts up,

    Bernhard Schussek

    unread,
    Jun 3, 2015, 10:06:14 AM6/3/15
    to php...@googlegroups.com
    I agree with Jan. The only real benefit I see from this standard is using multiple containers side-by-side, and I don't understand why anyone would want to do that.

    --

    --
    You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
    To post to this group, send email to php...@googlegroups.com.

    Marco Pivetta

    unread,
    Jun 3, 2015, 10:48:54 AM6/3/15
    to php...@googlegroups.com
    On 3 June 2015 at 15:05, Bernhard Schussek <bsch...@gmail.com> wrote:
    I agree with Jan. The only real benefit I see from this standard is using multiple containers side-by-side, and I don't understand why anyone would want to do that.

    That's the actual use-case: we got a load of meta-packages (Bundles/Modules/Extensions) that just provide service bindings for specific frameworks.

    If we were able to simply join them, then we'd reduce the need for these meta-packages (or their framework specialization).

    An example could be:

     - require package orm-provider-services
     - require package elasticsearch-provider-services
     - create service "orm-provider-services/base-config" in the app
     - create service "elasticsearch-provider-services/base-config" in the app
     - run your app on whatever framework is psr-Y compliant (this PSR)

    This is just an example, but I'm maintaining service bindings for similar packages and it's just painful to have different solutions for every single FW where you'd want to consume those services.

    This PSR proposal is *NOT* about end-users, but about reducing bloat in meta-packages. jeremeamia/acclimate-container is a good example of where we want to go from here.

    @Jan: sorry, didn't find the time to reply further - my short and rantful response was due to the points stated above + me writing from a cellphone.

    David Négrier

    unread,
    Jun 3, 2015, 10:53:47 AM6/3/15
    to php...@googlegroups.com
    I completely agree with what Marco said.

    But let me give you another completely different example.

    @Jan, I'm not going to answer all of your questions at once, but I'll focus on one particular point. You seem to not find any convincing scenario for ContainerInterop. Let me imagine a scenario that was never discussed here so far.

    Let's picture yourself in 2017.

    You have this great website developed using Drupal 8. It is a mortgage comparator. In this website, you have a special page that allows visitors to find the cheapest mortgage. Therefore, since this is Drupal 8, you probably have in your code a "MortgageService" and a services.yml file with a "mortgageService" instance configured in it.

    Now, suddenly, your boss wants to expose this service as an API. Of course, you could do it using Drupal/Symfony tools, but you have seen this super-cool tool named Apigility with its sleek UI that streamlines most of the work to build an RPC API.

    How great would that be to use Apigility. Hopefully, both Drupal 8 and Apigility 2 are PSR-7 compatible (remember this is 2017 :) ). So using a good deal of middlewares (maybe zendframework/stratigility ?), you can have Apigility and Drupal 8 working side-by-side.

    At this point, you have installed Apigility. In Apigility, you create a "RPC resource" (that is an instance of a class), and you want to inject into this resource your "mortgageService".... Ho but wait! "mortgage" service is defined in Drupal 8 which relies on Symfony container, and Apigility is using Zend Container! Damn!

    Without container interoperability, that's fairly simple: you are screwed! However, with container interoperability, all you have to do is edit Zend DI container (the module.config.php file) and add a reference to "mortgageService" to the constructor of the RPC resource class.

    I hope you will agree with me that:

    - I never used the ContainerInterface as a service locator (yes, I know the difference between service locator and dependency injection, I've been working on this topic for the last 6 years)
    - I found a real-life use case for having 2 containers in a single application
    - All this is possible thanks to the delegate-lookup feature described in the PSR pre-draft, and since the delegate-lookup feature requires the ContainerInterface, it is necessary to have this interface.

    Does this seem to be a valid use case for you?

    David.

    PS: on a side note, you said: "it basically show the PHP community is in the hands of immature self-proclaimed "PHP FIG" group". Please notice that neither myself nor Matthieu Napoli, nor Marco Pivetta, nor most of the people who worked on container-interop are part of the PHP-FIG. So you should definitely not blame the PHP-FIG when it is me proposing this interface and no acceptance vote has started. Furthermore, people here are definitely skilled and I can say with certitude that I became of better developer by reading the topics on this list in the last 2 years, and by getting feedback from the community at large when working on container-interop. PHP community rocks, if you know how to listen.

    Lukas Kahwe Smith

    unread,
    Jun 3, 2015, 11:18:24 AM6/3/15
    to php...@googlegroups.com

    > On 03 Jun 2015, at 16:48, Marco Pivetta <ocra...@gmail.com> wrote:
    >
    > On 3 June 2015 at 15:05, Bernhard Schussek <bsch...@gmail.com> wrote:
    > I agree with Jan. The only real benefit I see from this standard is using multiple containers side-by-side, and I don't understand why anyone would want to do that.
    >
    > That's the actual use-case: we got a load of meta-packages (Bundles/Modules/Extensions) that just provide service bindings for specific frameworks.
    >
    > If we were able to simply join them, then we'd reduce the need for these meta-packages (or their framework specialization).
    >
    > An example could be:
    >
    > - require package orm-provider-services
    > - require package elasticsearch-provider-services
    > - create service "orm-provider-services/base-config" in the app
    > - create service "elasticsearch-provider-services/base-config" in the app
    > - run your app on whatever framework is psr-Y compliant (this PSR)

    There are also libraries that are sufficiently complex that there is a need to for lazy loading dependencies but still wanting to allow for extensibility. For example in Jackalope we do not use “new” but instead we have a factory that is injectable by the end user. Furthermore the core of Jackalope requires a Jackalope transport implementation which might also want to override certain aspects.

    here is the Jackalope core factory implementation:
    https://github.com/jackalope/jackalope/blob/master/src/Jackalope/Factory.php

    inside a transport implementation an end user can inject their own implementation or we fallback to the core one:
    https://github.com/jackalope/jackalope-doctrine-dbal/blob/master/src/Jackalope/RepositoryFactoryDoctrineDBAL.php#L77

    however we have one transport implementation for which we wanted to optimize a specific case with the query model so we created a custom factory:
    https://github.com/jackalope/jackalope-jackrabbit/blob/master/src/Jackalope/Jackrabbit/Factory.php

    Which is then what we use by default in the Repository factory:
    https://github.com/jackalope/jackalope-jackrabbit/blob/master/src/Jackalope/RepositoryFactoryJackrabbit.php#L75

    From what I gather from Benjamin’s twitter messages, similar things exist in Doctrine ORM.

    regards,
    Lukas Kahwe Smith
    sm...@pooteeweet.org



    signature.asc

    Lukas Kahwe Smith

    unread,
    Jun 3, 2015, 11:29:25 AM6/3/15
    to php...@googlegroups.com
    Now that I have stated where I think such a PSR can be useful, let me explain some of my hesitation.
    Using this PSR for framework interop to for example share an instance of Doctrine ORM between two logic units of code (potentially 2 applications mixed together in a single request thanks to PSR-7), I wonder if its not more practical to simply write some glue code that sets instances of Doctrine ORM created in the first application explicitly into the DI Container of the 2nd application. Do I really need the same container in both? Especially as a get() method requires a name, which would then also need to be standardized which seems quite unrealistic.

    So such glue code could look like this:
    $orm = $app1->getContainer()->get(‘doctrine’);
    $app2->getContainer()->set(‘orm’, $orm);

    This seems trivial enough and much more realistic since it automatically deals with the potential for mismatches in service names and potential framework specific configuration settings might also need to be set on the service (and maybe need to be unset when going back to the 1st app).
    signature.asc

    Jan Jakeš

    unread,
    Jun 3, 2015, 11:43:43 AM6/3/15
    to php...@googlegroups.com
    @Marco:

    Big part of the problem of complicated metapackages might be an insufficiently good DI in your app or (historically) not very DI friendly packages (not always clean services with hidden dependencies). If the Elasticsearch package has its own DI, than it's very very wrong to me. No library ever should depend on DI or service locator.

    With Nette DI we are able to completely setup Doctrine in only a couple of lines of NEON (something like YAML but more powerful for DI) config and that's it - no meta-package. If it's harder, you can write your own CompilerExtension - compare this Assetic integration (https://github.com/tripomatic/nette-assetic/blob/master/src/DI/AsseticExtension.php) to that one of Symfony (many times more lines since Symfony is not so DI clean as Nette and Nette has a better DI Container implementation). But yeah, you are right that these are still just metapackages and it's hard to mantain them. But that does not allow a package to depend on a DI container (because the it's not a DI) - solution would be probably something like Chris has suggested - standardize the configuration of the DI.

    @David:

    There is one thing in your story that is very wrong and if 2017 will be like that, it's sad :) I'm speaking about this:

    "mortgage" service is defined in Drupal 8 which relies on Symfony container, and Apigility is using Zend Container! Damn!"

    The problems are "relies on Symfony container" and "is using Zend Container" - this should have never ever happened in the first place! Why the packages depend on some DI container? That's a mistake in their architecture. I would take half a day and write a simple compiler extension for any services I need to incorporate in my code, that's it. If you look at some quickstart for Doctrine, you see the services you need to initialize to have fully configured entity manager - instead of writing this bootstraping quickstart code you either write it to your DI config or with a more powerful compiler extension.

    We (in Tripomatic) solve integrations of many different libraries on a daily basis and nothing ever took us more than a couple of hours with Nette DI.

    And one little point "I never used the ContainerInterface as a service locator" - well your code apparently knows about the DI container and is dependent on it so you haven't used it as a DI either.

    And finally "I found a real-life use case for having 2 containers in a single application" - I absolutely believe you but that doesn't make it right and that doesn't justify this PSR which breaks DI (similarly, 6 years of experience isn't a proof that you can't be mistaken although you probably have great programming knowledge).

    To end this post I'm happy to see that guys like Fabien Potencier or Anthony Ferrara share my opinion:

    Fabien Potencier:
    Simple: core classes not aware of the DIC == DI, the design pattern, used correctly
    DIC != service locator

    Anthony Ferrara:
    DI Containers / Service Locators should be details inside of your application. If your libraries depend on them, you're doing it wrong (tm)


    Hope my explanations are understandable,

    Bernhard Schussek

    unread,
    Jun 3, 2015, 11:45:57 AM6/3/15
    to php...@googlegroups.com
    2015-06-03 16:48 GMT+02:00 Marco Pivetta <ocra...@gmail.com>:
    On 3 June 2015 at 15:05, Bernhard Schussek <bsch...@gmail.com> wrote:
    I agree with Jan. The only real benefit I see from this standard is using multiple containers side-by-side, and I don't understand why anyone would want to do that.

    That's the actual use-case: we got a load of meta-packages (Bundles/Modules/Extensions) that just provide service bindings for specific frameworks.

    I agree with the problem, but not with the solution. The consequence of this approach would be that we have to instantiate all container implementations that are required by *any* loaded package. In the worst case you could have something like 4 or 5 containers running side by side. One single DI container can be highly optimized, but multiple parallel ones can't.

    Second, Bundles/Modules/Extensions usually don't just provide service bindings, but also configuration and other ways to dynamically augment the bindings. The way this configuration is expressed and loaded is highly framework specific.

    So, I agree that we should get rid of these meta-packages, but I don't think we can get rid of duplicated DI configuration. Instead, a package could contain multiple configuration files/classes for different DI containers. If you use the package, you'll load the adequate configuration for the DI container of your app.

    It's not super nice for the maintainer, but it's nicer than what we have now and I think the best we can get.

    @David: The example you gave can be solved without this PSR, as you can register services in one container that are dynamically loaded from the other container as Lukas pointed out. I don't think that's a strong argument.

    David Négrier

    unread,
    Jun 3, 2015, 12:13:17 PM6/3/15
    to php...@googlegroups.com
    Are you sure about the "Interface" in the interface class name? I mean, there is no ArrayAccessInterface as far as I know.

    Actually, the PSR bylaws about conventions state that an interface MUST be suffixed with "Interface":

    https://github.com/php-fig/fig-standards/blob/master/bylaws/002-psr-naming-conventions.md

    This is what was done for PSR-3 and PSR-7 already.

    David
    Twitter: @david_negrier
    Github: @moufmouf
    Website: http://mouf-php.com

    David Négrier

    unread,
    Jun 3, 2015, 12:37:45 PM6/3/15
    to php...@googlegroups.com
    Especially as a get() method requires a name, which would then also need to be standardized which seems quite unrealistic.

    Definitely, standardizing names seems unrealistic. There is a big gap between container based on auto-wiring and containers based on configuration files. But you can use aliases to go around this problem.
    Furthermore, if your container does not support aliasing, you can add it using the ContainerInterface.
    Have a look at this pet project: https://github.com/thecodingmachine/alias-container
    It's a simple class that takes a container in parameter and adds aliasing support.

    Using the ContainerInterface, you can extend existing containers with additional behaviour (another use case we have not yet spoke about).

    Think about adding aliasing capabilities, or lazy loading capabilities to an existing container that does not provide those.....

     

    David Négrier

    unread,
    Jun 3, 2015, 1:02:05 PM6/3/15
    to php...@googlegroups.com
    Hi Bernhard,


    So, I agree that we should get rid of these meta-packages, but I don't think we can get rid of duplicated DI configuration. Instead, a package could contain multiple configuration files/classes for different DI containers. If you use the package, you'll load the adequate configuration for the DI container of your app.

    I'd definitely like to avoid this scenario if possible! As a package developer, I certainly don't want to have to bother learning all the configuration files from all the existing frameworks! Just imagine the pain of writing a services.yml, then a module.config.php, then PHP callback for Pimple, PHP-DI annotations, Mouf installer, then what... there is this NEON configuration format I just learned about today? This is definitely not what I call "interoperability".

    Now, I do agree with you when you say:


    In the worst case you could have something like 4 or 5 containers running side by side. One single DI container can be highly optimized, but multiple parallel ones can't.

    To this, I would like to point out that multiple PSR-7 middleware will certainly slow down your application, and still, we are fairly happy to have those around! So if you are into performances, you may want to avoid having multiple routers in your application, but it is still fairly cool to be able to do it when performance is not a key issue.

    So bouncing on Marco's answer, the future might look like this:

    - vendor/mypackage : the package a developer develops
    - vendor/mypackage-universalmodule : provides a container with services already configured
    - vendor/mypackage-bundle : a specially crafted module for Symfony 2/3
    - vendor/mypackage-zfmodule : a specially crafted module for ZF

    If you are a Symfony user, just use the bundle! By all means. It will be more performant. Yet, the "universalmodule" package is very useful for the rest of the PHP developers out there that are not Symfony 2 users (believe me, there are quite a lot).

    Also, obligatory Donald Knuth quote :) :
    Premature optimisation is the root of all evil.


    Finally, the cleanest way around this would be to standardize a CompilerPass mechanism, but you should consider that most DI containers out there have no notion of compilation, so it is kind of a dead end, unless you want to rule 90% of the existing containers out of this PSR.


    David.
    Twitter: @david_negrier
    Github: @moufmouf

    Márk Sági-Kazár

    unread,
    Jun 3, 2015, 1:24:45 PM6/3/15
    to php...@googlegroups.com
    It seems to me that the conversation's direction is "how knows better" now. I agree that decent conversation requires to be polite otherwise you cannot be taken seriously.

    Beyond the fact whether this PSR breaks DI concepts or not, there are some things that should be taken into consideration:

    1. As the meta document says, most of DI implementations can be configured differently (in fact, this is what they are really different from each other), but the purpose is the same: to retrieve something from the container. If that is true, then why should we standardize the way we populate the container? Why not the way we get something from it? It is already very similar in different containers. This seems illogical to me. If something, the retrieval should be standardized.

    2. Although the PSRs main goal is to standardize DI containers, who said that containers can only be DICs? And another question related to this: who said that DICs cannot be used as simple containers storing any kind of data? (I admit it is rather weird, but not impossible) For example: League/Route uses League/Container (not necessarily, but deafults to it) to store routes and uses it to create requests (when using a request-response strategy). So it not just stores routes, but also resolves a request from it, which might be service location, but I don't think it is any worst than using a factory. DI is simply not possible there, so why would it be a misuse? (Some people claims it to be a misuse as well)

    3. While service location is (considered to be) an anti-pattern (by most of the world), there are cases where it is easier and useful. For example in some kind of plugin system where you want to override some sort of resource. (AFAIK phpspec extension part does something similar, correct me if I am wrong). So in case it is simply easier, why spend the valuable software engineer hours (wait, this is open source) on creating a solution which might adhere the DI concepts, but much harder to use or requires unnecessary complexity.7

    I tried to provide a few cases where this PSR would be useful, but not (entirely) related to the DI concept breaking argument.


    2015. június 1., hétfő 15:05:45 UTC+2 időpontban David Négrier a következőt írta:
    Hi list!

    So PSR-7 being finally accepted, time to focus on other would-be PSRs :)

    I proposed in February to move container-interop to the PHP-FIG.
    Since then, I have had a chance to talk with a number of PHP community members, and to gather some feedback.

    Using this, I wrote a first pre-draft version of a "PSR-Container":

    - Container interface
    - Meta document

    Paul M. Jones agreed to be the coordinator for this PSR and Jeremy Lindblom will act as the second sponsor.

    Also, adoption of container-interop has kept improving, with Aura.DI being a fully compatible implementation, and the next release of Slim (the HTTP micro router) being container agnostic, thanks to container-interop.

    Finally (although a bit off-topic) I wrote a small article explaining why PSR-7 and PSR-Container are a perfect match for designing framework agnostic modules

    I'd be very interested into gathering as much feedback as possible from this pre-draft (although we already gathered a lot), and then, Paul can hopefully open the entrance vote.

    Best regards,

    Paul M. Jones

    unread,
    Jun 3, 2015, 3:39:51 PM6/3/15
    to php...@googlegroups.com
    Hi all,

    Leo Feyer just voted -1 on the entrance, with this comment:

    > I would prefer to see a set() method in the interface. Of course I have read section 3.2 of the meta document and I’ve also been loosely following the container-interop project, therefore I know about the goals of the PSR.
    >
    > Still I think that only get() and has() is not enough to really make it interoperable.


    I think the comment is fair, and I don't want to dispute either the vote or the comment here.

    Having said that, please note that a +1 at this time indicates only that you think the proposal is worthy of further discussion, not that it is imperfect or not fully formed.

    If someone thinks the proposal is "not quite enough", voting for entrance might be the better way to open up the discussion and have new suggestions implemented during the "Draft" phase that follows.

    That is all.

    Paul Dragoonis

    unread,
    Jun 3, 2015, 7:44:39 PM6/3/15
    to php...@googlegroups.com
    --
    You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
    To post to this group, send email to php...@googlegroups.com.

    For more options, visit https://groups.google.com/d/optout.

    I can see why people have objections, and they're fair ones.

    On the other hand, PPI Framework has developed their own Interop-container for the past year or so now, and PPI 2.1 is used in production and working well.


    Ours is pretty simple, it's a ZF2 and Symfony2 complaint servicemanager/container, and we often pass our own ZF2 service manager into Symfony2 code to pull out services.

    This PSR isn't for everyone, but if other projects apart from ZF2 and SF2 were compliant with this PSR then PPI would be able to consume more and more of the eco-system.

    This isn't for everyone, but it would benefit our project, which is why we voted +1.




     

    Lukas Smith

    unread,
    Jun 4, 2015, 1:23:02 AM6/4/15
    to php...@googlegroups.com


    On 03 Jun 2015, at 18:37, David Négrier <david....@gmail.com> wrote:

    Especially as a get() method requires a name, which would then also need to be standardized which seems quite unrealistic.

    Definitely, standardizing names seems unrealistic. There is a big gap between container based on auto-wiring and containers based on configuration files. But you can use aliases to go around this problem.
    Furthermore, if your container does not support aliasing, you can add it using the ContainerInterface.
    Have a look at this pet project: https://github.com/thecodingmachine/alias-container
    It's a simple class that takes a container in parameter and adds aliasing support.

    Using the ContainerInterface, you can extend existing containers with additional behaviour (another use case we have not yet spoke about).

    Think about adding aliasing capabilities, or lazy loading capabilities to an existing container that does not provide those.....

    and what if 'doctrine' is the EntityManager for one and a ManagerRegistry for another?

    regards,
    Lukas

    David Négrier

    unread,
    Jun 4, 2015, 4:43:03 AM6/4/15
    to php...@googlegroups.com
    Hi Lucas,

    True enough, 2 instances could have the same name in 2 containers, which might lead to problems. Actually, this might even happen pretty often.

    It might not be the only solution, but I've came up with this technique:

         https://github.com/thecodingmachine/prefixer-container

    It's basically namespacing for the container entries.

    It acts as a decorator around a container. Inside a container, you can access container entries normally, but if you want to access the same instance from "the outside", you have to prefix it with its "namespace". So in your example, using this prefixer technique, we would have "containerA.doctrine" and "containerB.doctrine". Have a look at the readme if you want to see the details, it explains in how this is working.

    ++

    David.

    Twitter: @david_negrier
    Github: @moufmouf

    Lukas Kahwe Smith

    unread,
    Jun 4, 2015, 5:03:21 AM6/4/15
    to php...@googlegroups.com

    > On 04 Jun 2015, at 10:43, David Négrier <david....@gmail.com> wrote:
    >
    > Hi Lucas,
    >
    > True enough, 2 instances could have the same name in 2 containers, which might lead to problems. Actually, this might even happen pretty often.
    >
    > It might not be the only solution, but I've came up with this technique:
    >
    > https://github.com/thecodingmachine/prefixer-container
    >
    > It's basically namespacing for the container entries.
    >
    > It acts as a decorator around a container. Inside a container, you can access container entries normally, but if you want to access the same instance from "the outside", you have to prefix it with its "namespace". So in your example, using this prefixer technique, we would have "containerA.doctrine" and "containerB.doctrine". Have a look at the readme if you want to see the details, it explains in how this is working.

    I once created this Bundle (which could of course also just been a lib):
    https://github.com/liip/LiipContainerWrapperBundle

    The idea was to deal with potential issues of re-useable Controllers into which people inject the controller.
    signature.asc

    Larry Garfield

    unread,
    Jun 9, 2015, 1:16:07 AM6/9/15
    to php...@googlegroups.com
    On 06/01/2015 08:05 AM, David Négrier wrote:
    Hi list!

    So PSR-7 being finally accepted, time to focus on other would-be PSRs :)

    I proposed in February to move container-interop to the PHP-FIG.
    Since then, I have had a chance to talk with a number of PHP community members, and to gather some feedback.

    Using this, I wrote a first pre-draft version of a "PSR-Container":

    - Container interface
    - Meta document

    Paul M. Jones agreed to be the coordinator for this PSR and Jeremy Lindblom will act as the second sponsor.

    Also, adoption of container-interop has kept improving, with Aura.DI being a fully compatible implementation, and the next release of Slim (the HTTP micro router) being container agnostic, thanks to container-interop.

    Finally (although a bit off-topic) I wrote a small article explaining why PSR-7 and PSR-Container are a perfect match for designing framework agnostic modules

    I'd be very interested into gathering as much feedback as possible from this pre-draft (although we already gathered a lot), and then, Paul can hopefully open the entrance vote.

    It is clear that a lot of thought has been put into this proposal already.  The meta doc in particular is quite extensive.

    Nonetheless, I will be voting no on Entrance, and encourage others to do so as well.

    My objection boils down, fundamentally, to two points.  One, quoting from the metadoc:

    -----

    It is important to distinguish the two usages of a container:

    • configuring entries
    • fetching entries

    Most of the time, those two sides are not used by the same party. While it is often end users who tend to configure entries, it is generally the framework that fetches entries to build the application.

    This is why this interface focuses only on how entries can be fetched from a container.
    -----

    The distinction between configuring (putting into the container) and fetching (pulling out from the container) is a good one.  However, the proposal seeks to standardize *the wrong one*.  "Fetching" is the process of pulling data out of the container.  That is, asking for a service.  Asking for a dependency.  Asking, rather than being told.

    No matter how you slice it, this is standardizing a Service Locator... NOT a Dependency Injection Container.  98% of code should NOT be accessing the container, and thus a standard interface for doing so is entirely irrelevant.  Of that other 2%, 1% is edge cases like lazy-factories, implemented for performance reasons, and 1% is low-level bootstrap to kick off the application.  Both are valid exceptions to the "container aware is harmful" rule.  Neither is, I believe, a compelling use case, especially given the downsides of encouraging a Service Locator-style syntax. 

    In the 98% case, what code is "pulling" services out of the container?  The container itself, so that it can inject them into other services.  The container obviously knows what its own syntax is, and the syntax of other containers is entirely irrelevant to it.  This is a solution in search of a problem.

    The only place that a container would need to care about the interface of another container is in the the case of delegated or nested containers, which is called out as a major use case.  Which brings me to my second objection: I believe that nested/delegated containers is a fundamentally bad idea and one that FIG should not in any way encourage.  I believe it is actively harmful.  I might be convinced otherwise, but I doubt it, and must vote based on my views at this time.

    Specifically, this approach encourages each library that has multiple services that need to get wired up to provide its own container to be delegated to.  That is, a library like Guzzle, or Monolog, or Solarium, or whatnot would, with this model, be encouraged to provide its own mini-container for the default wiring of its own services.  Then the consuming application would wire each of those mini-containers together as delegate containers of the main container.

    Which means that it is impossible for that main container to make any optimizations across all services.  Consider the case of the Symfony DependencyInjection component.  It has a multi-pass approach that allows service definitions to be modified before the final container is built.  That final container is a single PHP class with a method per service, which in turn will lazy-load the dependent services on the fly.  It's quite fast, once compiled, because at runtime it's just one single class and a bunch of method calls.  It can even omit some method services for private services.  (There is a bit more to it than that, but that's not relevant to this discussion.)

    If various services are coming in from a variety of different sub-containers, such optimization is impossible.  Each delegated service load incurs an extra runtime cost, and makes compile-time optimizations more difficult or impossible.  Compiler passes (the service definition modifiers) become unpredictable because I may need to deal with multiple containers for "configuring entries".  The spec says configuring entries is out of scope, but the approach encouraged actively makes configuring entires *harder*.  If I want to wire up a library I'm consuming differently than the default provided by the author (say, put in a different data storage backend, or swap out some component for a more optimized-for-my-application version, or all of the other things that good DI lets you do), then I have to either concern myself with that particular library's mini-container syntax -- thus defeating the point of a PSR -- or simply ignore it and wire everything up in my main container manually...  thus completely defeating the purpose of this PSR.

    Too, the idea of every library shipping its own mini-container is terrible.  Writing a highly optimized container is non-trivial.  And container performance *does* matter at scale.  That's something we're dealing with in Drupal 8 right now; there's quite a bit of time spent loading services, which we're trying to optimize using proxies, tweaking autoloading, eliminating dependencies, etc.  If we instead had to deal with a half dozen different containers chained together, that becomes an order of magnitude harder, if not impossible.

    In short, I believe this PSR is not unnecessary; it is actively counter-productive and harmful.

    What would be useful is, in fact, the exact opposite: Provide a common standard for putting stuff *into* the container.  Having every library provide its own unoptimized mini-container is a terrible idea.  But if it could provide a default configuration suggestion to any container?  Ie, eliminate the need for a Symfony Bundle, Zend Module, or Drupal module whose sole purposes is to wire stuff up into the container?  Now we're talking!  That would be useful.  That would allow for more experimentation and optimization without harming interoperability.  That is something I would support.

    But I do not believe it is wise for FIG to try and standardize the part of a container that should be least relevant.  To do so is counter-productive in many ways.

    --Larry Garfield

    André R.

    unread,
    Jun 9, 2015, 5:45:21 AM6/9/15
    to php...@googlegroups.com
    Thanks for this post Larry,

    it puts words on exactly why we decided to stay away on this one.

    Best,
    André Rømcke
    eZ Publish  (eZ Platform)

    David Négrier

    unread,
    Jun 9, 2015, 12:36:39 PM6/9/15
    to php...@googlegroups.com
    Hi Larry, hi list,

    First of all, thanks a lot for your constructive feedback (I mean it!)

    I have been AFK for a few days and a lot happened in this thread.

    We have had a lot of great feedback from very interested people, and if the response to this proposal has been mostly positive, there has also been some criticism I want to address.

    Negative feedback was generally not about the content of the PSR, but rather about whether we need this PSR at all, and whether there is a good use case for it. Top notch developers like Fabien Potencier, Antony Ferrara, Bernhard Schussek or Larry Garfield have expressed their dismay at this proposal, and often with very valid comments. Guys, this blog post is for you. I do not expect you to fully agree with me, but at least, I want you to see where we are headed.

    For this post, I’ll focus in this mail on use cases.

    We have come to great length giving a bunch of use cases where this PSR might be helpful. These use cases are a bit scattered all over the PHP-FIG mailing list, so I'll try to summarize all those use-cases in this blog post.

    As you read, you may not agree with one use case or another use case. You might even be completely right, and maybe some of those use cases are simply bad ideas (tm). In short, I do not expect you, reader, to agree with me on all this.

    However, please note that I only need one of those use-cases to be valid for PSR-11 to be worthwhile!

    Let's get started!


    Use case 1: container agnostic libraries


    Some libraries rely on a container to run:

    - some routers need to instantiate the controller they are using
    - a library like ["silly"](http://mnapoli.fr/silly-cli/) can rely on the container to inject parameters into a closure (dependency injection the way Angular does it)
    - some libraries are complex enough to need the ability to configure a container ( [Jackalope](https://groups.google.com/d/msg/php-fig/xC1CCjtyVnw/-XM0k7m_VlAJ) or Doctrine come to mind).

    Most of the negative feedback about this come from the fact that this means injecting the container into the library, which is "bad".

    Now, let me say I completely agree that injecting the container in user-land is a very bad practice (this means advocating the service locator design pattern).
    But this is not user-land we are injecting the container into! This is a third-party library! As [stated by Larry](https://groups.google.com/d/msg/php-fig/xC1CCjtyVnw/A3uZ-8HOaUIJ), if 99% of the libraries don’t need a container,
    there could be 1% very valid use-cases where a container is needed. For instance [here, in Symfony router](https://github.com/symfony/symfony/blob/2.8/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php#L65),
    or [here, in Silex](https://github.com/silexphp/Silex/blob/1.2/src/Silex/CallbackResolver.php#L50-L54),
    or [here, in PHP-DI/Invoker](https://github.com/PHP-DI/Invoker).

    Related Twitter thread: https://twitter.com/ircmaxell/status/606038237845594113

    Use case 2: universal module system

    The idea here is to develop framework agnostic meta-packages (i.e. Bundles/Modules/Extensions)

    Most meta-packages are providing instances or routes. Thanks to PSR-7, a package can provide routes in a framework agnostic way (using a Middleware). Thanks to PSR-11, we could do the same for container entries.

    Rather than providing a configuration file (services.yml, module.config.php…), you could instead provide a container loaded with entries.

    The container can be automatically added to a composite container containing all the containers used in the application.

    Bernhard Shussek [pointed out that this could have adverse effects on performance](https://groups.google.com/d/msg/php-fig/xC1CCjtyVnw/AfT48ZI3McUJ).
    Larry Garfield also [pointed out the problem of performance](https://groups.google.com/d/msg/php-fig/xC1CCjtyVnw/A3uZ-8HOaUIJ).
    It is true that several containers cannot perform better than a single container, but there are optimizations techniques that could be applied to improve performance.
    For instance, a composite container (usually the « root » container) could build a map of all entries with their associated container (instead of calling the `has` method on each container).
    This would be kind of similar to what happens when you build a classmap in Composer with the « -o » parameter.

    Possible alternative

    Jan Jakeš and Larry Garfield made a very valid point: for this use case, [we should instead focus on building a compiler extension](https://groups.google.com/d/msg/php-fig/xC1CCjtyVnw/s9hFplt18RAJ)
    that adds entries during the compilation of the container. First of all, thank you guys for proposing this alternative. I must admit **I am pretty fond of this solution**.
    Now, the truth is that most containers do not have a compilation pass mechanism. I would be interested in feedback about this, but so far,
    I think I saw support for compilation in Zend DI and Symfony only.

    Also, this means that we should standardize the API for defining entries in containers. This could be much more difficult than the current PSR-11 proposal.
    This has a number of advantages too (performance-wise). Those 2 proposals (container-interop and compiler extension standardization) only overlap on this particular use case,
    so I would tend to view those proposals as complementary rather than opposite.

    I honestly don’t think I have enough expertise to design a PSR for container compilation extensions, but I would gladly like to see one.

    I'm also planning to write a longer answer on this particular issue sometime later, because I want to speak here of all use cases, and not focus too much on this particular one. Still, it needs more attention, so expect a longer answer from me some time later.

    Use case 3: extending existing containers with additional features

    By having a generic interface to read entries from containers, you can start developing generic « wrappers » or « middlewares ».

    This can be tremendously useful to extend an existing container with new features.

    Here are a few samples:

    - A [CompositeContainer that aggregates several containers](https://github.com/jeremeamia/acclimate-container/blob/master/src/CompositeContainer.php) into a unique one.
    - A « jail » for exposing only some services (by Lukas Kahwe Smith: liip/LiipContainerWrapperBundle )
    - An [alias container](https://github.com/thecodingmachine/alias-container) that adds aliasing capabilities to any container
    - [Containers’ entries namespacing](https://github.com/thecodingmachine/prefixer-container) to avoid naming conflicts
    - A container wrapper that adds lazy-loading capabilities to any container (does not exists yet, but would be nice :) )
    - ...

    Just imagine being able to do something like this:

    Adding lazy-loading capabilities to Pimple

    $pimple = new Pimple();
    $pimple['entry'] = $pimple->share(function() { //… });

    $myContainer = LazyLoadingWrapper($pimple);

    // By adding "lazy." in front of an entry, it gets wrapped into a proxy object.
    $lazyLoadedObject = $myContainer->get('lazy.entry');
    // Now, the $lazyLoadedObject will only be fetched in Pimple when it is used for the first time.



    I’m not completely sure but I don’t think I read criticisms of this use case so far.

    Use case 4: side-by-side frameworks


    This is a copy from this message

    Picture yourself in 2017: you have this great website developed using Drupal 8. It is a mortgage comparator. In this website, you have a special page that allows visitors to find the cheapest mortgage. Therefore, since this is Drupal 8, you probably have in your code a "MortgageService" and a services.yml file with a "mortgageService" instance configured in it.


    Now, suddenly, your boss wants to expose this service as an API. Of course, you could do it using Drupal/Symfony tools, but you have seen this super-cool tool named Apigility with its sleek UI that streamlines most of the work to build an RPC API.

    How great would that be to use Apigility. Hopefully, both Drupal 8 and Apigility 2 are PSR-7 compatible (remember this is 2017 :) ). So using a good deal of middlewares (maybe zendframework/stratigility ?), you can have Apigility and Drupal 8 working side-by-side.

    At this point, you have installed Apigility. In Apigility, you create a "RPC resource" (that is an instance of a class), and you want to inject into this resource your "mortgageService".... Ho but wait! "mortgage" service is defined in Drupal 8 which relies on Symfony container, and Apigility is using Zend Container! Damn!

    Without container interoperability, that's fairly simple: you are screwed! However, with container interoperability, all you have to do is edit Zend DI container (the module.config.php file) and add a reference to "mortgageService" to the constructor of the RPC resource class.


    Most of the criticism here stems from the fact that one should never have 2 frameworks living side-by-side.

    See: https://twitter.com/ircmaxell/status/606038843557593089 and https://groups.google.com/d/msg/php-fig/xC1CCjtyVnw/FGmqo5gHtRgJ

    To this, I would like to point out that my use case is perfectly valid, that I might want to use both Apigility and Drupal 8 that are great tools, and that no, I don't want to spend 1 week rewiring Apigility into Drupal 8 using Drupal 8 container. This would simply be plainly stupid since I'm pretty sure I would break a bunch of things when I upgrade. I live in the real world. I find tools, I want them to work together. I don't need to be a framework specialist to do so.

    Use case 5: leaving some room for innovation in container space

    This reason is quite personal, and maybe the reason why I got involved with container interop in the first place.

    There is a huge place for innovation in DI containers. Containers answer the same problem (bootstraping an application) in very different ways (autowiring, configuration files, annotations, closures...)
    I believe there are other very valid techniques out there that have not been found yet.

    I am the lead developer of Mouf. Mouf is a dependency injection framework. It lacks a ton of features:
    it has no autowiring, no lazy-loading, no aliasing, no annotation support... But it has one feature that
    no other framework has: a graphical user interface with container configuration via drag'n'drop. I do truly believe
    that this is quite innovative, and I'm fairly proud of it. Trust me, it rocks. A typical container in any PHP application will contain about 30 to 40 services, because it is quite inconvenient to put more objects into it. Using Mouf, I’m not only putting services and controllers, I’m also putting views, widgets, forms, any fields making a form, etc… into the container. I have applications with containers containing happily 1000+ instances. Some people might say this is crazy, yet, it works! So believe me, there IS room for innovation.

    So... I've been developing this great tool, I want to share it with the rest of the world. What are my options?

    If I go out there and say "Hey! Come and see this brand new DI tool!", how many people will come and use it?
    The answer is easy... noone! Because in order to build an application, you have to wire a router, a db connection,
    an ORM, a templating system, .... How many developers out there are qualified enough to do such a thing? Probably
    only a tiny fraction of the PHP developer base. And how many will be willing to rewire everything to test this
    new DI tool? Probably none.

    You might have built a fairly innovative DI container, the chances that your ideas get adopted are null
    unless you manage to lower the barrier of adoption. How do you do that? You cannot take an existing framework, remove its container
    and replace it by your container. In theory, this should be possible (because the container is supposed to bootstrap the whole application).
    In practice, it just does not work this way. So the only other option is to plug your container to an
    existing full-stack framework that people know (Laravel, Symfony, ZF, Yii, etc...). The fact is this PSR makes it possible, thanks to delegate lookup.

    To sum it up:

    => PSR-11 = More innovation

    Once more, having 2 containers side-by-side is not an ideal situation, especially performance-wise.
    Yet, without this possibility, I really feel we are hindering innovation. It is almost impossible
    to innovate in this field if you are not a part of a big framework... and big frameworks tend to be
    quite conservative when it comes to their core. Opening the game (thanks to the delegate lookup of
    dependencies) will lead to innovation.

    Final word

    At this point, I'm sure that some people will disagree with one use-case or another (Larry, Bernhard, Jan, most of what you said remains true and I do not expect you to
    change your mind). But can you really say that because you don't like use-case X or use-case Y, this whole PSR is not worthwhile? Have you really considered all possible use cases?

    Also, this PSR is NOT about advocating using the service locator pattern. As you probably noticed in the 5 use cases I have been presenting,
    none of them is about having a standard service locator to be used in user-land.

    I believe that a PSR should be rated on what useful use cases it can offer, not on what bad things could happen if it is misused, because you can always misuse something.

    I'd be glad to discuss further in this thread, especially about use cases that have been seldom spoken about (use-case 3 and 5).

    Also, @Larry, I did not fully answer your post yet, but expect from me a more detailed answer to your proposal about standardizing the way we put things into a container, there is really much to be said about it, and it is a very interesting topic.

    Jan Jakeš

    unread,
    Jun 10, 2015, 7:40:43 AM6/10/15
    to php...@googlegroups.com
    Hi all,

    I'm happy to see that more and more people understand how harmful this PSR would be if it passed.

    For those who disagree and don't care about violating the principles of DI I'll try to express why this PSR is wrong on a different level with an example with routing. I choose routing because DI implementation is nothing else than just another package an we should not give it a special status. This analogy thus might be clearer:

    Interoperability = I can choose any package that implements router (to my app using any framework).
    Interoperability != I will use many different routers and connect them together because other packages I've choosen depend on them!

    Now replace router with DI or anything else and you'll see what this PSR is trying to do. Accepting it means officially supporting and motivating framework and package developers to use very bad practises, wire their own poor DI containers to their code, and violate the DI itself. Don't get me wrong - nobody says they can't do that, it just shouldn't be standardized.

    ---
    Now, I'll try to briefly respond to David (but I'll probably repeat myself):

    > However, please note that I only need one of those use-cases to be valid for PSR-11 to be worthwhile!

    I strongly disagree. Are you saying that anything that has at least one single use-case should have a standard? That's a very strange kind of argumentation to me.

    > Use case 1: container agnostic libraries

    The fact that such libraries exist doesn't make it right and doesn't justify existence of a PSR supporting this bad practise. As Larry mentioned this PSR "is actively counter-productive and harmful".

    > Use case 2: universal module system

    To quote Larry's great post again: "What would be useful is, in fact, the exact opposite: Provide a common standard for putting stuff *into* the container."

    Why do you think this: "Rather than providing a configuration file (services.yml, module.config.php…), you could instead provide a container loaded with entries." is a better solution than what Larry and Kris suggest (standardize putting stuff into container)? In my opinion it's not only terribly bad from a "good-practise view" but it's simply a completely wrong "lets just wire it somehow" non-systematic solution. Again, the fact that standardizing container configuration would probably be much harder doesn't justify standardizing the wrong way to do it.

    > Use case 3: extending existing containers with additional features

    What we should have is "ability to choose any (but only ONE) DI implementation" the same way as we choose Zend's Diactoros for implementing PSR-7 interfaces and the same way as we whould be able to choose a single router, etc.

    Does anybody add capabilities to existing routers in a general way (i.e. the same way to all routers)? No, because their capabilities are implementation-specific and even an idea of doing that seems odd. I think a big problem around this PSR is that some of the frameworks don't have real DI containers but just some sort of configurator-that-I-call-DI and maybe even think-is-a-DI. 

    > Use case 4: side-by-side frameworks

    First, a framework should be nothing than a concrete choice of a DI container and a set of any packages that know nothing about the container. The fact that most of the frameworks are not there yet does not mean we have to make a bad standard. Second, with a good DI integrating even a larger package to your app would take no more than a couple of hours.

    > Use case 5: leaving some room for innovation in container space

    Actually, the only "innovation" is the inner implementation and a form of configuring the container since your code should know absolutely nothing about the container. If it does know about it than it's not a DI.

    I don't know Mouf, but:
    > ...because it is quite inconvenient to put more objects into it...
    > ...have applications with containers containing happily 1000+ instances...
    > ...Some people might say this is crazy, yet, it works!...

    I think this comes from many bad DI implementations and a wrong idea about DI. I have absolutely no idea why I would need something like Mouf (and the whole UI idea stinks to me a lot, sorry). We do have thousands of classes in our container, we do not think it's crazy, we've been using this for years, and we do not find it inconvenient to put more objects into it. See:

    - Tripomatic\WeatherForecast\OpenWeatherMap\ApiWrapper(\Guzzle\Http\Client(%openWeatherMap.url%))
    - Tripomatic\WeatherForecast\OpenWeatherMap\ApiResponseMapper
    - Tripomatic\WeatherForecast\SunService
    - Tripomatic\WeatherForecast\WeatherForecastController
    - Tripomatic\WeatherForecast\WeatherForecastOutputBuilder
    ...

    Does this look inconvenient? Why would I need an UI for that?

    > I believe that a PSR should be rated on what useful use cases it can offer, not on what bad things could happen if it is misused, because you can always misuse something.

    This PSR itself is a misuse of DI and a very harmful idea to just quickly glue anything together. 

    ---
    I've probably repeated myself a lot but I feel it has to be repeated to avoid a terribly wrong decision. For some people it might be hard or impossible to admit because they might have spent months on doing this the "wrong way". But - refusing this PSR won't forbid anybody to do projects like "acclimate-container" - their existence itself just cannot justify making a wrong standard. Thats all.

    Seeing the votes I see a big chance this PSR will never make it to the end. Then we can focus on ideas how to "put things into container" in a standard way and I'll be happy to help.

    Thanks for reading up to the end and please don't take my criticism personally - I'm just criticizing essentially different understandings of DI that I consider wrong.

    Best,
    Jan


    Dne pondělí 1. června 2015 15:05:45 UTC+2 David Négrier napsal(a):
    Hi list!


    So PSR-7 being finally accepted, time to focus on other would-be PSRs :)

    I proposed in February to move container-interop to the PHP-FIG.
    Since then, I have had a chance to talk with a number of PHP community members, and to gather some feedback.

    Using this, I wrote a first pre-draft version of a "PSR-Container":

    - Container interface
    - Meta document

    Paul M. Jones agreed to be the coordinator for this PSR and Jeremy Lindblom will act as the second sponsor.

    Also, adoption of container-interop has kept improving, with Aura.DI being a fully compatible implementation, and the next release of Slim (the HTTP micro router) being container agnostic, thanks to container-interop.

    Finally (although a bit off-topic) I wrote a small article explaining why PSR-7 and PSR-Container are a perfect match for designing framework agnostic modules

    I'd be very interested into gathering as much feedback as possible from this pre-draft (although we already gathered a lot), and then, Paul can hopefully open the entrance vote.

    Best regards,

    Bernhard Schussek

    unread,
    Jun 10, 2015, 7:41:11 AM6/10/15
    to php...@googlegroups.com
    Thank you for taking the time for this detailed and well researched write-up David. A short summary of my thoughts on your use cases:

    UC 1: From my experience, tools that really need to access the DIC need more than just get()/has(). They either need to access services by name, or by class, or by a tag, or they need to query the available service IDs by some property, etc.

    UC 2: This UC can IMO only be solved by standardizing the configuration, not the fetching, as Larry pointed out.

    UC 3: Again I don't think you can add any useful functionality in a wrapper of a DIC if you can't access the underlying definition of its services.

    UC 4: I don't think it's a good idea to use two frameworks in one project. Different libraries, yes, but not different frameworks (= architecture styles). I would solve your UC by creating two completely separate applications that talk to the same data storage or by using a SOA.

    UC 5: that's the same as UC 3 from what I see

    For me, UC 2 is the most interesting use case and the one I want to see solved, but not with the approach proposed in this PSR (again for the reasons given by Larry). The other use cases are not really relevant to me at the moment. IMO the group should focus on more important topics in the near future (like the currently unfinished PSRs).

    Cheers,
    Bernhard

    --

    --
    You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
    To post to this group, send email to php...@googlegroups.com.

    Larry Garfield

    unread,
    Jun 10, 2015, 11:51:21 AM6/10/15
    to php...@googlegroups.com
    I believe Bernhard and Jan have covered the response to David's latest
    post fairly well. I ask my fellow voting reps to reject the idea of a
    container interface, and instead encourage work on a container
    *configuration* standard, which would be beneficial to many projects.

    In particular, the idea that such a standard is only useful to a
    compiling container like Symfony and Zend use is untrue. Reading a JSON
    file or YAML file or XML file or whatever and parsing that into calls to
    $pimple->share() would not be all that difficult. Different than for
    Symfony DI, sure, but that's the point; you would need one "glue piece"
    from the configuration standard to each DI implementation (ie, about a
    dozen) and then you're done. Any library that wants to offer itself up
    that way is now ingestable into any container as a first-class citizen.

    That's where any FIG effort on container should be placed.

    --Larry Garfield

    On 6/10/15 6:40 AM, Jan Jakeš wrote:
    > Hi all,
    >
    > I'm happy to see that more and more people understand how harmful this
    > PSR would be if it passed.
    >
    > For those who disagree and don't care about violating the principles of
    > DI I'll try to express why this PSR is wrong on a different level with
    > an example with routing. I choose routing because DI implementation is
    > nothing else than just another package an we should not give it a
    > special status. This analogy thus might be clearer:
    >
    > *Interoperability = I can choose any package that implements router (to
    > my app using any framework).*
    > *Interoperability != I will use many different routers and connect them
    > together because other packages I've choosen depend on them!*
    >
    > Now replace router with DI or anything else and you'll see what this PSR
    > is trying to do. *Accepting it means officially supporting and
    > motivating framework and package developers to use very bad practises,
    > wire their own poor DI containers to their code, and violate the DI
    > itself.* Don't get me wrong - nobody says they can't do that, it just
    > shouldn't be standardized.
    >
    > ---
    > Now, I'll try to briefly respond to David (but I'll probably repeat myself):
    >
    > /> However, please note that I only need one of those use-cases to be
    > valid for PSR-11 to be worthwhile!/
    >
    > I strongly disagree. Are you saying that anything that has at least one
    > single use-case should have a standard? That's a very strange kind of
    > argumentation to me.
    >
    > /> Use case 1: container agnostic libraries/
    >
    > The fact that such libraries exist doesn't make it right and doesn't
    > justify existence of a PSR supporting this bad practise. As Larry
    > mentioned this PSR "is actively counter-productive and harmful".
    >
    > /> Use case 2: universal module system/
    >
    > To quote Larry's great post again: /"What would be useful is, in fact,
    > the exact opposite: Provide a common standard for putting stuff *into*
    > the container."/
    >
    > Why do you think this: /"Rather than providing a configuration file
    > (services.yml, module.config.php…), you could instead provide a
    > container loaded with entries."/ is a better solution than what Larry
    > and Kris suggest (standardize putting stuff into container)? In my
    > opinion it's not only terribly bad from a "good-practise view" but it's
    > simply a completely wrong "lets just wire it somehow" non-systematic
    > solution. Again, the fact that standardizing container configuration
    > would probably be much harder doesn't justify standardizing the wrong
    > way to do it.
    >
    > /> Use case 3: extending existing containers with additional features/
    >
    > What we should have is /"ability to choose any (but only ONE) DI
    > implementation"/ the same way as we choose Zend's Diactoros for
    > implementing PSR-7 interfaces and the same way as we whould be able to
    > choose a single router, etc.
    >
    > Does anybody add capabilities to existing routers in a general way (i.e.
    > the same way to all routers)? No, because their capabilities are
    > implementation-specific and even an idea of doing that seems odd. I
    > think a big problem around this PSR is that some of the frameworks don't
    > have real DI containers but just some sort of
    > configurator-that-I-call-DI and maybe even think-is-a-DI.
    >
    > /> Use case 4: side-by-side frameworks/
    >
    > First, a framework should be nothing than a concrete choice of a DI
    > container and a set of any packages that know nothing about the
    > container. The fact that most of the frameworks are not there yet does
    > not mean we have to make a bad standard. Second, with a good DI
    > integrating even a larger package to your app would take no more than a
    > couple of hours.
    >
    > /> Use case 5: leaving some room for innovation in container space/
    >
    > Actually, the only "innovation" is the inner implementation and a form
    > of configuring the container since your code should know absolutely
    > nothing about the container. If it does know about it than it's not a DI.
    >
    > I don't know Mouf, but:
    > /> ...because it is quite inconvenient to put more objects into it.../
    > /> ...have applications with containers containing happily 1000+
    > instances.../
    > /> ...Some people might say this is crazy, yet, it works!.../
    >
    > I think this comes from many bad DI implementations and a wrong idea
    > about DI. I have absolutely no idea why I would need something like Mouf
    > (and the whole UI idea stinks to me a lot, sorry). We *do* have
    > thousands of classes in our container, we *do not* think it's crazy,
    > we've been using this for years, and we *do not* find it inconvenient to
    > put more objects into it. See:
    >
    > -
    > Tripomatic\WeatherForecast\OpenWeatherMap\ApiWrapper(\Guzzle\Http\Client(%openWeatherMap.url%))
    > - Tripomatic\WeatherForecast\OpenWeatherMap\ApiResponseMapper
    > - Tripomatic\WeatherForecast\SunService
    > - Tripomatic\WeatherForecast\WeatherForecastController
    > - Tripomatic\WeatherForecast\WeatherForecastOutputBuilder
    > ...
    >
    > Does this look inconvenient? Why would I need an UI for that?
    >
    > /> I believe that a PSR should be rated on what useful use cases it can
    > offer, not on what bad things could happen if it is misused, because you
    > can always misuse something./
    >
    > This PSR itself is a misuse of DI and a very harmful idea to just
    > quickly glue anything together.
    >
    > ---
    > I've probably repeated myself a lot but I feel it has to be repeated to
    > avoid a terribly wrong decision. For some people it might be hard or
    > impossible to admit because they might have spent months on doing this
    > the "wrong way". But - refusing this PSR won't forbid anybody to do
    > projects like "acclimate-container" - their existence itself just cannot
    > justify making a wrong standard. Thats all.
    >
    > Seeing the votes I see a big chance this PSR will never make it to the
    > end. Then we can focus on ideas how to "put things into container" in a
    > standard way and I'll be happy to help.
    >
    > Thanks for reading up to the end and please don't take my criticism
    > personally - I'm just criticizing essentially different understandings
    > of DI that I consider wrong.
    >
    > Best,
    > Jan
    >
    >
    > Dne pondělí 1. června 2015 15:05:45 UTC+2 David Négrier napsal(a):
    >
    > Hi list!
    >
    > So PSR-7 being finally accepted, time to focus on other would-be PSRs :)
    >
    > I proposed in February to move container-interop to the PHP-FIG
    > <https://groups.google.com/forum/#!searchin/php-fig/container-interop/php-fig/o_jFaRoLfAo/UBbNznHzp7gJ>.
    > Since then, I have had a chance to talk with a number of PHP
    > community members, and to gather some feedback.
    >
    > Using this, I wrote a first pre-draft version of a "PSR-Container":
    >
    > - Container interface
    > <https://github.com/container-interop/fig-standards/blob/master/proposed/container.md>
    > - Meta document
    > <https://github.com/container-interop/fig-standards/blob/master/proposed/container-meta.md>
    >
    > Paul M. Jones agreed to be the coordinator for this PSR and Jeremy
    > Lindblom will act as the second sponsor.
    >
    > Also, adoption of container-interop has kept improving, with Aura.DI
    > being a fully compatible implementation, and the next release of
    > Slim (the HTTP micro router) being container agnostic, thanks to
    > container-interop.
    >
    > Finally (although a bit off-topic) I wrote a small article
    > explaining why PSR-7 and PSR-Container are a perfect match for
    > designing framework agnostic modules
    > <http://mouf-php.com/psr7-container-interop-equals-cross-framework-module-system>
    >
    > I'd be very interested into gathering as much feedback as possible
    > from this pre-draft (although we already gathered a lot), and then,
    > Paul can hopefully open the entrance vote.
    >
    > Best regards,
    >
    > David.
    > Twitter: @david_negrier
    > Github: @moufmouf
    >
    > --
    > You received this message because you are subscribed to the Google
    > Groups "PHP Framework Interoperability Group" group.
    > To unsubscribe from this group and stop receiving emails from it, send
    > an email to php-fig+u...@googlegroups.com
    > <mailto:php-fig+u...@googlegroups.com>.
    > To post to this group, send email to php...@googlegroups.com
    > <mailto:php...@googlegroups.com>.
    > To view this discussion on the web visit
    > https://groups.google.com/d/msgid/php-fig/8bcddaa5-a0ad-4491-bba4-58a6ebca8728%40googlegroups.com
    > <https://groups.google.com/d/msgid/php-fig/8bcddaa5-a0ad-4491-bba4-58a6ebca8728%40googlegroups.com?utm_medium=email&utm_source=footer>.

    David Négrier

    unread,
    Jun 10, 2015, 1:24:03 PM6/10/15
    to php...@googlegroups.com
    Sorry Larry, Jan and Bernhard but I strongly believe you are wrong.

    Let me tell you why.

    Your whole point is that PSR-11 should be written the other way around and we should standardize the way we put things into a container rather than standardize the way we pull things out of a container.

    The soundest way to do this is certainly to standardize a CompilerPass mechanism, as can be found in Symfony, although there could be other options like standardizing a configuration file format. Larry makes a pretty good work at explaining why it is a better idea, and it comes down to this: performance and optimization possibilities.

    The fact is that when we first started thinking about container-interop (2 years ago), we thought about this and we went down this path (see here)
    When I say "we", I mean all the great people who contributed to container-interop. I may be the only one advocating a container-interop PSR in this very mailing list, but be sure I am not a lone wolf :)

    So let's go down the path of standardizing how we put things into a container, and let's see where this leads.

    Configuration VS runtime containers


    You can divide containers into 2 categories:

    - The ones that rely on configuration files (Symfony 2, ZF2, Nette, Mouf). Usually, you cannot put anything in these containers at runtime.
    - The ones that are filled at runtime by PHP code... usually using closures or autowiring (Pimple, Aura, Laravel...)



    Note: if the picture does not display correctly, I put the content of this post here in this blog article.

    The line is not completely clear with some containers crossing boundaries (like PHP-DI).

    Runtime containers cannot be compiled. It makes no sense for these.


    Standardizing a configuration file or a compilation pass

    On the other hand, containers based on configuration files can be compiled. Not all of those have the capability though. SF2, ZF2 and Nette have support for compilation.
    Mouf has not (yet) support for it. If we were to standardize how a compilation pass is performed, then that would force all configuration-based frameworks into implementing
    compilation. I'm not saying it is bad (compilation is great for performance), yet, we would dictate a feature.

    Let's continue down that path.

    So now, we need to write an interface that describes an object stored in a container (what Symfony calls a "Definition").
    For the sake of this post, let's call this interface the DefinitionInterface (a possible alternative would be to describe a JSON format, most of what I see below stays true)
    Obviously, we need to be able to put a class name in that definition, and also constructor parameters.
    Then, we need to be able to set any public property (at this point, you can expect a very long thread on the PHP-FIG mailing list with lots of people explaining that you should not standardize setting public properties because that's bad (tm) )
    Then, we need to be able to set any setter. Have a look at the frameworks around. Mouf does only support 'setters' (functions starting by setXXX). If I'm correct, Nette only support methods starting with "injectXXX".
    ZF2 and Symfony support any method call, with any number of parameters. This is clearly the best option, because it is the most flexible. So we take this solution.
    Which means that both Mouf and Nette will have to **adapt** to support method calls.

    Now, you realize that some frameworks have support for public or private entries, or even a notion of "context". If you do add these concepts to the `DefinitionInterface`,
    you are forcing more features into frameworks that do not have this concept. On the other hand, if you do not put these features, you are hindering advanced DI containers from there full power.

    And then, there is the question of supporting tags, and aliasing, and feature X, Y, Z..... At the end of the day, there is a real risk that your `DefinitionInterface`
    will contain all the features of all the existing frameworks.

    And then, you realize something wrong happened. The DefinitionInterface does not dictate what a container should provide, it dictate HOW it should provide it.
    Such a PSR would force a number of features into containers.
    At the end of the day, all containers will look the same, supporting the same features! This PSR would not promote diversity.
    Instead, it would make all containers look like Symfony DI container. Which is pointless of course.

    An interface is a contract. It should not matter how your class fulfills the contract. In this regard, I feel that the ContainerInterface proposed for PSR-11 is great. But in the case of the DefinitionInterface, my feeling is that we are dictating too much.

    What makes a container different from another container is the way you put things into it! There is no way you can standardize that without making all containers look the same.

    Standardizing how to set things in a runtime container

    At this point, we only spoke about configuration based container.
    The other containers (runtime containers) would actually be way easier to standardize. Almost all of them has a "set" method that takes a callback in parameter.

    Yeah, I know, this is not the best you can do in terms of performance because you have to call "set" on each instance at runtime. Some PHP-FIG members will call it 
    a bad practice (tm), and will tell you that compilation is the only way to go.
    Yet, there are tons of containers out there that actually work this way (hello Pimple!). And a number of micro-frameworks actually 
    expect to be able to put things in the container at runtime (Silex and Slim for instance).
    And it is way easier to standardize "set" than a compiler pass or configuration file... so what about this?

    And what about containers that are purely based on auto-wiring, or containers that are using annotations? Are we completely ruling them out?

    Summary


    Note: if the picture does not display correctly, I put the content of this post here in this blog article.

    Regarding performance, I plan to do some tests to see if this is a real issue or not. I'll keep you posted.

    One last thing: I would absolutely love to see a common container format for many packages that is not bound to a particular framework.
    But I feel this format should be open to competition, not dictated by a PSR. Basically, if ContainerInterface is accepted, it will be possible for PHP developers to write containers that scan your application and packages for configuration files, that will compile those files, and that will make them available to the main container. Each container can have its own format.
    At the end of the day, maybe one format will win over the others, just like Composer won over PEAR. This format would become a de-facto standard (until a better one appears), and this is way better than trying to dictate a format in the PHP-FIG mailing list.
    The `ContainerInterface` is the glue you need to make this competition possible.

    Larry Garfield

    unread,
    Jun 10, 2015, 2:38:42 PM6/10/15
    to php...@googlegroups.com
    David,

    I must return the "you're wrong" favor here. :-) Your description of
    what such a format would need to do is, I believe, so far off base it
    borders on FUD.

    Background: My container experience is almost entirely Symfony and
    Pimple. I have not worked with the others mentioned here. However,
    seeing that there are any containers that work only by magically named
    setters or magically named public properties makes me cry inside.

    Your argument is basically that in order to cover all use cases, we
    would need to basically reimplement the Symfony services.yml format in
    all its glory, which forces all containers to become the Symfony
    container. That is extremely untrue. Such a PSR would be as basic as
    possible, and I would go as far as advocating that it only support
    constructor injection. That doesn't preclude anyone else from having
    their own formats a la services.yml that support 50 different things,
    but it covers the common case of "I've a library with 5 classes that
    should get wired up this way by default".

    Rather than debate in the abstract, I will simply give an example for
    Pimple.

    disney/dwarf package, services.json:

    {
    'services': {
    'dwarf_factory': {
    'class': 'Disney\DwarfFactory'
    }
    'dwarf_manager': {
    'class': 'Disney\DwarfManager',
    'arguments': ['@dwarf_factory', 4]
    }
    }
    }


    index.php (likely wrapped up into a provider for Silex, or similar):

    $services = json_decode(file_get_content('services.json'));
    foreach ($services['services'] as $name => $def) {
    $container[$name] = function($c) use ($def) {
    if (!isset($def['arguments']) {
    return new $def['class'];
    }
    $args = [];
    foreach ($def['arguments'] as $argument) {
    $args[] = strpos($argument, '@') !== false
    ? $c[substr($argument, 1)];
    : argument;
    }
    return new $def['class'](...$args); // Yay, PHP 5.6!
    }
    }

    And we're done. For every package I consume in, say, Silex, I just call
    $app->registerPsrServices('services.json'); or whatever, and poof,
    they're all registered and named and everything. Symfony would have
    entirely different code that converts that JSON into its own Definition
    objects to get compiled. Others can do whatever it is they do, but we
    wouldn't need to have a per-package wiring library. 'course, if you
    want to bypass the library's recommended wiring you can just ignore its
    JSON file and do your own thing, or modify the configuration if your
    container supports it, or...

    Best part: This imposes *nothing* on the services themselves. Nothing
    is container aware. It's totally easy to do. The glue is all in the
    containers. At runtime, there is only one container. And for a
    runtime-only container, the overhead of the code above is pretty small.
    It's a couple of if-statements and a small-n foreach loop.

    We do not need to go further down that path! Just as we left a whole
    lot of stuff out of PSR-7 to focus on the essence of it, we focus on the
    essence here. "I got these constructors, put 'em together". I've not
    worked with an auto-wiring container but I'm sure with that metadata and
    some reflection it could auto-wire whatever else it needs based on just
    that little data.

    So now, I don't believe that addressing the configuration side is the
    rats nest you claim it is. On the contrary, now that I write the above
    I kind of wonder why we haven't done it yet, when it took me about 10
    minutes to do. :-) We just need to not support every possible feature
    under the sun, which you are very correct would lead down a rabbit hole
    of dictating implementation. So let's not do that. We don't have to do
    that.

    And the above would have a much more positive impact on interoperability
    and ease of pulling in new packages than nesting containers inside each
    other.

    --Larry Garfield

    On 6/10/15 12:23 PM, David Négrier wrote:
    > Sorry Larry, Jan and Bernhard but I strongly believe you are wrong.
    >
    > Let me tell you why.
    >
    > Your whole point is that PSR-11 should be written the other way around
    > and we should standardize the way we put things into a container rather
    > than standardize the way we pull things out of a container.
    >
    > The soundest way to do this is certainly to standardize a CompilerPass
    > <http://symfony.com/doc/current/cookbook/service_container/compiler_passes.html> mechanism,
    > as can be found in Symfony, although there could be other options like
    > standardizing a configuration file format. Larry makes a pretty good
    > work at explaining why it is a better idea, and it comes down to this:
    > performance and optimization possibilities.
    >
    > The fact is that when we first started thinking about container-interop
    > (2 years ago), we thought about this and we went down this path (see
    > here <https://github.com/container-interop/container-interop/issues/1>)
    > When I say "we", I mean all the great people who contributed to
    > container-interop. I may be the only one advocating a container-interop
    > PSR in this very mailing list, but be sure I am not a lone wolf :)
    >
    > So let's go down the path of standardizing how we put things into a
    > container, and let's see where this leads.
    >
    > Configuration VS runtime containers
    >
    >
    > You can divide containers into 2 categories:
    >
    > - The ones that rely on configuration files (Symfony 2, ZF2, Nette,
    > Mouf). Usually, you cannot put anything in these containers at runtime.
    > - The ones that are filled at runtime by PHP code... usually using
    > closures or autowiring (Pimple, Aura, Laravel...)
    >
    >
    > ​
    > Note: if the picture does not display correctly, I put the content of
    > this post here in this blog article
    > <http://mouf-php.com/psr-11-put-vs-get-entries>.
    >
    > The line is not completely clear with some containers crossing
    > boundaries (like PHP-DI).
    >
    > Runtime containers cannot be compiled. It makes no sense for these.
    >
    >
    > Standardizing a configuration file or a compilation pass
    >
    > On the other hand, containers based on configuration files can be
    > compiled. Not all of those have the capability though. SF2, ZF2 and
    > Nette have support for compilation.
    > Mouf has not (yet) support for it. If we were to standardize how a
    > compilation pass is performed, then that would force all
    > configuration-based frameworks into implementing
    > compilation. I'm not saying it is bad (compilation is great for
    > performance), yet, we would *dictate* a feature.
    >
    > Let's continue down that path.
    >
    > So now, we need to write an interface that describes an object stored in
    > a container (what Symfony calls a "Definition
    > <http://api.symfony.com/2.7/Symfony/Component/DependencyInjection/Definition.html>").
    > Such a PSR would *force a number of features* into containers.
    > At the end of the day, all containers *will look the same*, supporting
    > the same features! This PSR would *not promote diversity*.
    > And what about containers that are purely based on *auto-wiring*, or
    > containers that are using *annotations*? Are we completely ruling them out?
    >
    > Summary
    >
    >
    > Note: if the picture does not display correctly, I put the content of
    > this post here in this blog article
    > <http://mouf-php.com/psr-11-put-vs-get-entries>.​
    >
    > Regarding performance, I plan to do some tests to see if this is a real
    > issue or not. I'll keep you posted.
    >
    > *One last thing*: I would absolutely love to see a common container
    > format for many packages that is not bound to a particular framework.
    > But I feel this format should be open to competition, not dictated by a
    > PSR. Basically, if ContainerInterface is accepted, it will be possible
    > for PHP developers to write containers that scan your application and
    > packages for configuration files, that will compile those files, and
    > that will make them available to the main container. Each container can
    > have its own format.
    > At the end of the day, maybe one format will win over the others, just
    > like Composer won over PEAR. This format would become a de-facto
    > standard (until a better one appears), and this is way better than
    > trying to *dictate* a format in the PHP-FIG mailing list.
    > The `ContainerInterface` is *the glue you need to make this competition
    > possible*.
    >
    > --
    > You received this message because you are subscribed to the Google
    > Groups "PHP Framework Interoperability Group" group.
    > To unsubscribe from this group and stop receiving emails from it, send
    > an email to php-fig+u...@googlegroups.com
    > <mailto:php-fig+u...@googlegroups.com>.
    > To post to this group, send email to php...@googlegroups.com
    > <mailto:php...@googlegroups.com>.
    > To view this discussion on the web visit
    > https://groups.google.com/d/msgid/php-fig/CABAasbcootVVz7J4Lrk2dDqsv0sWG3Ar-6vtoC5E0L4S0RLUbA%40mail.gmail.com
    > <https://groups.google.com/d/msgid/php-fig/CABAasbcootVVz7J4Lrk2dDqsv0sWG3Ar-6vtoC5E0L4S0RLUbA%40mail.gmail.com?utm_medium=email&utm_source=footer>.

    Glenn Eggleton

    unread,
    Jun 10, 2015, 3:32:18 PM6/10/15
    to php...@googlegroups.com
    Hi Bernhard,

    Currently some composer packages have their own DI container inside.
    I could see this being beneficial to integrate my apps container and a dependency's container.

    Glenn

    Larry Garfield

    unread,
    Jun 10, 2015, 5:34:06 PM6/10/15
    to php...@googlegroups.com
    Yes, some do. Encouraging more to do so is actively harmful.
    Encouraging fewer to do so by providing a configuration source instead
    is actively beneficial.

    That's basically the debate. :-) And why I'm encouraging people to vote
    no on the current Entrance vote.

    --Larry Garfield

    On 6/10/15 2:32 PM, Glenn Eggleton wrote:
    > Hi Bernhard,
    >
    > Currently some composer packages have their own DI container inside.
    > I could see this being beneficial to integrate my apps container and a
    > dependency's container.
    >
    > Glenn
    >
    > On Wednesday, June 3, 2015 at 10:06:14 AM UTC-4, Bernhard Schussek wrote:
    >
    > I agree with Jan. The only real benefit I see from this standard is
    > using multiple containers side-by-side, and I don't understand why
    > anyone would want to do that.
    >
    > --
    > Bernhard Schussek
    > Blog: http://webmozarts.com
    > Twitter: http://twitter.com/webmozart
    >
    > 2015-06-03 14:21 GMT+02:00 Jan Jakeš <j...@jakes.pro <javascript:>>:
    >
    > Christopher: You seem to be right about the tone of some of my
    > quotes, I'll pay attention to avoid that next time. I'll try to
    > respond to your points:
    >
    > 1. We don't need ContainerInterface for fetching services
    > because the correct way is not knowing about it in the code
    > (except fetching one service in bootstrap).
    > Someone has to bootstrap. That seems to be agreed upon. It
    > doesn't mean that the application or libraries you use need
    > to know about the container beyond the bootstrap phase.
    > Autowiring is great.
    > You are right that the existence of ContainerInterface won't
    > make it harder to use DI in a clear way. I want to point
    > more to my doubts that this interface is necessary (see more
    > below).
    >
    > 2. You can't mix autowiring and fetching by service names in
    > the same method. Doing so is a misunderstanding of basic
    > autowiring principles.
    > You can. Laravel is a great example of this working. Many
    > objects are resolved by service name. Many are resolved by
    > class names. A great majority are resolved by autowiring.
    > You can in a particular implementation. But there are DI's
    > that implement both with different methods - sure, we can
    > say that you can always put it to a single method and
    > prioritize types over names or the other way round, but -
    > isn't that already a sign that the interface won't be
    > universal enough? This is really more of a question - I am
    > not sure, maybe you've convinced me that a single get might
    > work...
    >
    > 3. Container interoperability is a wrong pattern and it cannot
    > be used among containers with different capabilities (the
    > problem is especially autowiring).
    > All containers (whether they support autowiring or not)
    > should be able to resolve an object. If that's all these
    > interfaces seek to standardise then I don't see why this is
    > a problem. I mean, it's basically saying; "if you can
    > resolve, then resolve like this or you don't conform to the
    > PSR". Perhaps I'm missing your intent with this.
    > I think (and I'll sum this up below) that the biggest
    > problem and from my point of view a "DI antipattern" is to
    > use multiple containers at all. What I wanted to say in
    > particular is that if one container wants to autowire a
    > parameter to a constructor of some service (by type) and
    > this container uses another container (that can reslove the
    > service for the parameter) over the interface - in case when
    > the second container is not able to fetch a service by type,
    > this autowiring resolution in the first container will fail,
    > won't it?
    >
    > 4. *You seem to think that a simple global service locator is
    > the same as DI Container.* The interface you've proposed and
    > <https://groups.google.com/forum/#!searchin/php-fig/container-interop/php-fig/o_jFaRoLfAo/UBbNznHzp7gJ>.
    > Since then, I have had a chance to talk with a number of PHP
    > community members, and to gather some feedback.
    >
    > Using this, I wrote a first pre-draft version of a
    > "PSR-Container":
    >
    > - Container interface
    > Paul M. Jones agreed to be the coordinator for this PSR and
    > Jeremy Lindblom will act as the second sponsor.
    >
    > Also, adoption of container-interop has kept improving, with
    > Aura.DI being a fully compatible implementation, and the
    > next release of Slim (the HTTP micro router) being container
    > agnostic, thanks to container-interop.
    >
    > Finally (although a bit off-topic) I wrote a small article
    > explaining why PSR-7 and PSR-Container are a perfect match
    > for designing framework agnostic modules
    > <http://mouf-php.com/psr7-container-interop-equals-cross-framework-module-system>
    >
    > I'd be very interested into gathering as much feedback as
    > possible from this pre-draft (although we already gathered a
    > lot), and then, Paul can hopefully open the entrance vote.
    >
    > Best regards,
    >
    > David.
    > Twitter: @david_negrier
    > Github: @moufmouf
    >
    > --
    > You received this message because you are subscribed to the
    > Google Groups "PHP Framework Interoperability Group" group.
    > To unsubscribe from this group and stop receiving emails from
    > it, send an email to php-fig+u...@googlegroups.com <javascript:>.
    > To post to this group, send email to php...@googlegroups.com
    > <javascript:>.
    > <https://groups.google.com/d/msgid/php-fig/d60cf2fd-337b-480a-8dac-423dc6c37705%40googlegroups.com?utm_medium=email&utm_source=footer>.
    >
    > For more options, visit https://groups.google.com/d/optout
    > <https://groups.google.com/d/optout>.
    >
    >
    > --
    > You received this message because you are subscribed to the Google
    > Groups "PHP Framework Interoperability Group" group.
    > To unsubscribe from this group and stop receiving emails from it, send
    > an email to php-fig+u...@googlegroups.com
    > <mailto:php-fig+u...@googlegroups.com>.
    > To post to this group, send email to php...@googlegroups.com
    > <mailto:php...@googlegroups.com>.
    > To view this discussion on the web visit
    > https://groups.google.com/d/msgid/php-fig/3b08d859-12b9-4c2b-b3b9-758dcebe3a0d%40googlegroups.com
    > <https://groups.google.com/d/msgid/php-fig/3b08d859-12b9-4c2b-b3b9-758dcebe3a0d%40googlegroups.com?utm_medium=email&utm_source=footer>.

    Glenn Eggleton

    unread,
    Jun 11, 2015, 10:14:16 AM6/11/15
    to php...@googlegroups.com
    Can you clarify on why it would be harmful? I struggle to see the problem with it.

    My view on what a container is... Libraries are programs. Programs should have their own global space. The Libraries Container creates this global space.

    My Program A uses Library B, C, D. Each of which have their own container. A does not need to know about the containers of B, or C, or D. Nor should they be able to access the contents of them because B, C, and D are each their own programs. Theoretically speaking: since we cannot tag references as const, everything is basically mutable. Something in A can change the dependency in B or C, or D thus causing an issue. 
    A accessing B or C or D also violates encapsulation.

    I would be in favor for a container interface that also some sort of scope attachment to prevent outside modules from accessing the internals.

    Just my thoughts.
    Glenn

    Woody Gilk

    unread,
    Jun 11, 2015, 11:40:25 AM6/11/15
    to php...@googlegroups.com
    My Program A uses Library B, C, D. Each of which have their own container.

    This is the problem with the current proposal. It assumes that libraries having a container is okay, when libraries being aware of a container is an anti-pattern.

    To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
    To post to this group, send email to php...@googlegroups.com.
    To view this discussion on the web visit https://groups.google.com/d/msgid/php-fig/7aa880e7-3d9e-42a5-821c-c1926f9b31ca%40googlegroups.com.

    For more options, visit https://groups.google.com/d/optout.
    --

    Jason Judge

    unread,
    Jun 11, 2015, 12:45:03 PM6/11/15
    to php...@googlegroups.com
    On Monday, 1 June 2015 19:38:26 UTC+1, Kris Wallsmith wrote:
    I am against standardizing a container interface because we would be implicitly endorsing the use of containers in application code (passing around containers), which is a bad practice. I would rather see FIG create a standard around configuring a container (i.e. Symfony's ContainerBuilder et al), so libraries could ship with one class that would add services to whatever container you are using in your application.

    Just out of curiosity, is there a way to specify "a PSR-7 container is needed" in composer.json? I realise composer isn't the be-all and end-all of everything. Would it just be down to documentation to inform developers what is needed, or perhaps the author listing their favourite containers in the composer.json `suggest` section?

    Marco Pivetta

    unread,
    Jun 11, 2015, 12:47:13 PM6/11/15
    to php...@googlegroups.com
    On 11 June 2015 at 16:40, Woody Gilk <woody...@gmail.com> wrote:
    My Program A uses Library B, C, D. Each of which have their own container.

    This is the problem with the current proposal. It assumes that libraries having a container is okay, when libraries being aware of a container is an anti-pattern.
     
    Well, as a matter of fact, libraries very often have a container or a factory/facade that builds/starts up the system as an entry point for consumers.
    Sometimes, this "container" is even re-used internally.
    For example, Doctrine ORM relies on a "configuration" object that is passed around and that contains various bits that can be replaced by a consumer of the library (OMG, he said library! And he said container! Burn him!).

    It doesn't need to be nice either, it just needs to "work", because nobody is going to re-configure something like PHPCR ODM from scratch anytime anyway.

    JNDI ( http://en.wikipedia.org/wiki/Java_Naming_and_Directory_Interface ) was largely successful and is very useful despite being (basically) a locator standardization.

    For the purists: no, I'm not going to rewrite an entire bootstrapper for everything I'll ever do with every library I use (just give me a service instance).

    Bernhard Schussek

    unread,
    Jun 11, 2015, 12:54:27 PM6/11/15
    to php...@googlegroups.com
    2015-06-11 18:46 GMT+02:00 Marco Pivetta <ocra...@gmail.com>:
    JNDI ( http://en.wikipedia.org/wiki/Java_Naming_and_Directory_Interface ) was largely successful and is very useful despite being (basically) a locator standardization.

    I don't think this is comparable. In a Java container (server), a service (generally) remains started once you start it. Accessing that service via a name makes a lot of sense. 

    With PHP's shared-nothing architecture, you can't have that. We need to take much more care that the bootstrapping of an application is as efficient as possible.

    Marco Pivetta

    unread,
    Jun 11, 2015, 1:04:58 PM6/11/15
    to php...@googlegroups.com
    On 11 June 2015 at 17:53, Bernhard Schussek <bsch...@gmail.com> wrote:

    2015-06-11 18:46 GMT+02:00 Marco Pivetta <ocra...@gmail.com>:
    JNDI ( http://en.wikipedia.org/wiki/Java_Naming_and_Directory_Interface ) was largely successful and is very useful despite being (basically) a locator standardization.

    I don't think this is comparable. In a Java container (server), a service (generally) remains started once you start it. Accessing that service via a name makes a lot of sense. 

    With PHP's shared-nothing architecture, you can't have that. We need to take much more care that the bootstrapping of an application is as efficient as possible.

    I'd rather reduce the scope of an app or build a long running process rather than trying to compile everything into a single container.
    I also don't believe in the standard E_NOT_JAVA argument, since I build long running processes without big problems (works great!).

    Standardizing the configuration format is possible, but we'd land into:
     - yaml mess (meh, I hate that, you'd get my straight -1 just because I'm allergic to yaml)
     - xml (people hate XML, but it's hard to explain them that it doesn't really bite, and you'd need to teach them how to read stack traces)
     - arrays (<sarcasm>we already have ZF2</sarcasm>)
     - annotations (much worse than locators and also goes against everything already said by purists)

    So yeah, service locator: take or leave. That's the interface we can standardize *now*.
    Everything else would be JSR-330-ish and would also be much less likely to be adopted cross-framework in first place.

    </snarky-response>, sorry

    Jordi Boggiano

    unread,
    Jun 11, 2015, 1:09:03 PM6/11/15
    to php...@googlegroups.com
    On 11/06/2015 17:45, Jason Judge wrote:
    > On Monday, 1 June 2015 19:38:26 UTC+1, Kris Wallsmith wrote:
    >
    > I am against standardizing a container interface because we would be
    > implicitly endorsing the use of containers in application code
    > (passing around containers), which is a bad practice. I would rather
    > see FIG create a standard around /configuring/ a container (i.e.
    > Symfony's ContainerBuilder
    > <https://github.com/symfony/symfony/blob/2.7/src/Symfony/Component/DependencyInjection/ContainerBuilder.php> et
    > al), so libraries could ship with one class that would add services
    > to whatever container you are using in your application.
    >
    >
    > Just out of curiosity, is there a way to specify "a PSR-7 container is
    > needed" in composer.json? I realise composer isn't the be-all and
    > end-all of everything. Would it just be down to documentation to inform
    > developers what is needed, or perhaps the author listing their favourite
    > containers in the composer.json `suggest` section?

    You could require a psr/container-implementation for example, which is a
    virtual package provided by all implementations of the psr/container
    interface.

    We already have that for psr/log:
    https://packagist.org/providers/psr/log-implementation

    and others https://packagist.org/search/?q=psr%20implementation

    Cheers

    Matthieu Napoli

    unread,
    Jun 11, 2015, 1:28:23 PM6/11/15
    to php...@googlegroups.com
    What is the difference between

    1. a shared config format, for example a PHP array:

    return [
        'foo' => 'bar',
    ];

    2. an object implementing ContainerInterface:

    class SimpleContainer implements ContainerInterface
    {
        public function get($id)
        {
            $entries = [            // pretend it's in the constructor
                'foo' => 'bar',
            ];
            if (! isset($entries[$id])) {
                throw
            }
            return $entries[$id];
        }
        ...
    }

    I see no conceptual difference here: how will the config array be used? Will it be modified? No. What operations are useful on that array? offsetGet and offsetExists. Oh wait, that's exactly what the ContainerInterface is about (get and has). Except relying on a format means relying on an implementation, whereas relying on the interface means *not caring about the implementation*.

    What I mean to say is that in this context, a PHP array, ContainerInterface or a ServiceProviderInterface (e.g. in Silex, Slim, …) have the same goal and same concept: the module or library provides container entries. DoctrineBundle or TwigServiceProvider f.e. exist for a reason.

    Performance wise, are we really sure there's a significant difference? Are we sure it's a definitive blocker and we shouldn't even look into it? Are we absolutely sure *we should rule out this idea entirely from the start because of that*?

    Or should we at least discuss the point? Remember this is not an acceptance vote.
    --
    You received this message because you are subscribed to a topic in the Google Groups "PHP Framework Interoperability Group" group.
    To unsubscribe from this topic, visit https://groups.google.com/d/topic/php-fig/xC1CCjtyVnw/unsubscribe.
    To unsubscribe from this group and all its topics, send an email to php-fig+u...@googlegroups.com.

    To post to this group, send email to php...@googlegroups.com.
    Message has been deleted

    Glenn Eggleton

    unread,
    Jun 11, 2015, 4:19:42 PM6/11/15
    to php...@googlegroups.com
    From a production view a container does have a few useful things like factory methods which allow the application to differ creating a service until it is required; however this is not actually considered in this meta documentation. I think the discussion should be changed to what Containers can do for us aside from the obvious of resolving dependencies.

    Example, I do not create an instance of my EmailSubsystem until it is needed. Maybe 5% of requests require an email, and since I wrap it in a factory, my application saves that time. since I am not wasting time creating that service.

    Slim v2 -> v3 is quite different in terms of writing a differed service. While I haven't fully explored the container space, I would imagine that each container library does it differently. Common tasks like factorizing a dependency would make this way more valuable.

    Glenn

    Woody Gilk

    unread,
    Jun 11, 2015, 4:33:43 PM6/11/15
    to php...@googlegroups.com
    On Thu, Jun 11, 2015 at 3:16 PM, Glenn Eggleton <gegg...@gmail.com> wrote:
    > Example, I do not create an instance of my EmailSubsystem until it is
    > needed. Maybe 5% of requests require an email, and since I wrap it in a
    > factory, my application saves that time. since I am not wasting time
    > creating that service.

    If only 5% of requests require an email, than only 5% of your
    responding classes (controller or domain or whatever pattern you use)
    should contain a reference to EmailSubsystem.

    Again, this is just another example of how a DI container can be
    abused and become an anti-pattern.

    Stefano Torresi

    unread,
    Jun 11, 2015, 6:23:39 PM6/11/15
    to php...@googlegroups.com
    Il giorno gio 11 giu 2015 alle ore 22:33 Woody Gilk <woody...@gmail.com> ha scritto:
    If only 5% of requests require an email, than only 5% of your
    responding classes (controller or domain or whatever pattern you use)
    should contain a reference to EmailSubsystem.

    Again, this is just another example of how a DI container can be
    abused and become an anti-pattern.

    FWIW I don't think this is a valid argument. Suboptimal dependency graphs are suboptimal regardless of how IoC is applied.

    This whole question about what is wrong and what isn't... is a bit like a religion discussion. 

    What I really see is that this proposal had so much demand already, that an unofficial standard has come up. Nearly 100k downloads.
    Concrete implementations are out in the wild.

    Frankly, seeing so many -1 to entrance asserting "this is so worthless I don't even want to discuss it" feels a bit short-sighted.

    Woody Gilk

    unread,
    Jun 11, 2015, 6:29:22 PM6/11/15
    to php...@googlegroups.com
    On Thu, Jun 11, 2015 at 5:23 PM, Stefano Torresi <ste...@torresi.io> wrote:
    > FWIW I don't think this is a valid argument. Suboptimal dependency graphs
    > are suboptimal regardless of how IoC is applied.


    The difference being that using DI in the way described hides the fact
    that the dependency graph is not optimized.

    David Négrier

    unread,
    Jun 12, 2015, 5:14:10 AM6/12/15
    to php...@googlegroups.com
    Hi Glenn,

    Woody is right here. I'll just extend a bit its answer.

    Basically, if somewhere in your controller, you are calling `$container->get('emailService')`, then it means that your controller knows about the container. Therefore, your controller could potentially call any service of the container. When looking at your controller/service constructor, it is not immediately obvious what your service or controller will need. This is why it is not recommanded to do so (this is what we call "using a container as a service locator").

    Note: even if it is not recommanded, most frameworks out there are still providing an instance of the container in the controller (see Symfony or Silex).

    Now, you are perfectly right to say that we should not waste time bootstraping unnecessary services. There are really 2 options here: one theoretical and one practical.

    In theory, the container should be called only once, at the very beginning of the application, to bootstrap all the graph of objects. In Java applications, this is ok, because they are long-lived. In PHP application, bootstraping all the objects is a waste of time and memory. But there is a solution around this problem: lazy services! Thanks to great libraries like Ocramius's ProxyManager, some container can create lazy services. These are "mock" objects that look like a service, and that instantiate the service only if a method is called on them. So in theory, you could write a router that holds references on proxies to all the controllers of the application. When the router selects a route, it picks the "lazy controller", and only this controller (and its dependencies) is fetched.

    In practice, I have not seen no router out there relying on lazy services provided by the container. What all frameworks out there are doing is that the router is holding a reference on the container. When the route is resolved, the router is calling the container 'get' method to fetch the matching controller. As Woody said, it is likely that your requests going through that controller will always need the EmailService, so you add a dependency from your controller on the emailservice. The emailservice will only be instantiated when the controller is instantiated, which should be good enough. To sum it up, if you want to write clean code, you should avoid at all cost calling the container directly. However, third party libraries (like a router) can have a need for calling the container directly (hence the ContainerInterface).
    Reply all
    Reply to author
    Forward
    0 new messages