From the About section of psr/container package on GitHub:
This repository holds all interfaces related to PSR-11 (Container Interface).
Note that this is not a Container implementation of its own. It is merely abstractions that describe the components of a Dependency Injection Container.
If we look at the code in this repository we can see that there are only three interface files.
ContainerInterface
ContainerExceptionInterface
NotFoundExceptionInterface
Let's take a look at ContainerInterface
interface file:
<?php
declare(strict_types=1);
namespace Psr\Container;
/**
* Describes the interface of a container that exposes methods to read its entries.
*/
interface ContainerInterface
{
/**
* Finds an entry of the container by its identifier and returns it.
*
* @param string $id Identifier of the entry to look for.
*
* @throws NotFoundExceptionInterface No entry was found for **this** identifier.
* @throws ContainerExceptionInterface Error while retrieving the entry.
*
* @return mixed Entry.
*/
public function get(string $id);
/**
* Returns true if the container can return an entry for the given identifier.
* Returns false otherwise.
*
* `has($id)` returning true does not mean that `get($id)` will not throw an exception.
* It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface`.
*
* @param string $id Identifier of the entry to look for.
*
* @return bool
*/
public function has(string $id): bool;
}
It has two method signatures. get()
and has()
. Any class that implements that interface must have definitions for these two methods. Let's see if Laravel's container has these methods.
Laravel Container
I am assuming every Laravel Developer knows that there's a Container. It's simply a class somewhere in the framework code. Let's perform a search in our code editor. We find two files named Container
.
-
Illuminate\Contracts\Container\Container.php
, this is an interface -
Illuminate\Container\Container
, this is an implementation of above interface
If we look at the above mentioned Container
interface file we can see that Laravel is extending the ContainerInterface
from psr/container
package and also adds some method signatures of its own.
<?php
namespace Illuminate\Contracts\Container;
use Closure;
use Psr\Container\ContainerInterface;
interface Container extends ContainerInterface
{
/**
* Determine if the given abstract type has been bound.
*
* @param string $abstract
* @return bool
*/
public function bound($abstract);
}
Now let's take a look at Laravel's Container
implementation class.
<?php
namespace Illuminate\Container;
use Illuminate\Contracts\Container\Container as ContainerContract;
class Container implements ContainerContract
{
/**
* {@inheritdoc}
*/
public function get($id)
{
try {
return $this->resolve($id);
} catch (Exception $e) {
if ($this->has($id) || $e instanceof CircularDependencyException) {
throw $e;
}
throw new EntryNotFoundException($id, $e->getCode(), $e);
}
}
/**
* {@inheritdoc}
*/
public function has($id)
{
return $this->bound($id);
}
/**
* Determine if the given abstract type has been bound.
*
* @param string $abstract
* @return bool
*/
public function bound($abstract)
{
return isset($this->bindings[$abstract]) ||
isset($this->instances[$abstract]) ||
$this->isAlias($abstract);
}
}
We can see that this class implements get()
and has()
method from ContainerInterface
of psr/container
package.
But, Why?
The real question here is, why go through all this trouble? Laravel team could have just made these interfaces and they wouldn't have to add another dependency to the framework?
PHP-FIG
PHP-FIG stands for PHP Framework Interop Group.
From FAQ section of website, aims of PHP-FIG:
- The idea behind the group is for project representatives to talk about the commonalities between our projects and find ways we can work together. Our main audience is each other, but we’re very aware that the rest of the PHP community is watching. If other folks want to adopt what we’re doing they are welcome to do so, but that is not the aim. Nobody in the group wants to tell you, as a programmer, how to build your application.
To understand it better, consider the following:
- Wouldn't it better if all PHP frameworks would follow a common definition of
Container
class? PHP-FIG has a recommended definition of theContainer
class and Laravel, Symfony and Yii ( to name a few frameworks ) follow this recommendation.
PSR
PSR stands for PHP Standards Recommendation. That's what PHP-FIG does, just provide Standards Recommendations. Any project ( framework ) is welcome to adopt this standard.
You can find the list of all PHP Standard Recommendations in numerical order here.
The numbers concatenated to PSR like PSR-4 and PSR-11 just represent the order in which these standards were submitted/approved.
Conclusion
In order to comply with PHP-FIG provided PSR-11 Container Interface recommendation, Laravel requires the psr/container
package.
Interesting facts about psr/container
in Laravel context
- Pull request for making Laravel's container compliant to PSR-11 Container Interface was opened by Marco Aurélio Deleu on 29 June, 2017 and was approved by Taylor Otwell.
- It was added in Laravel v5.5
- Laravel Container didn't have
get()
andhas()
method before compliance with PSR-11 Container Interface. -
make()
andbound()
methods were available alternatives on Laravel Container.
I hope you enjoyed this post. Next, we will see how Laravel uses psr/simple-cache
package. You can follow me on Twitter or join my newsletter for more content.
Top comments (0)