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