Skip to content

ContainerInterface Implementation

Rougin Gutib edited this page Sep 29, 2024 · 12 revisions

← Preparing New Project | "Components" Implementation →

As Slytherin tries to be extensible as much as possible, there are many ways on how to setup the Application instance. One of them is the ContainerInterface implementation which is the most important implementation for Slytherin.

Example Code

Below is an example code for creating a Slytherin-based application:

// app/web/index.php

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Rougin\Slytherin\Application;
use Rougin\Slytherin\Container\Container;
use Rougin\Slytherin\Http\Response;
use Rougin\Slytherin\Http\ServerRequest;
use Rougin\Slytherin\Routing\Dispatcher;
use Rougin\Slytherin\Routing\DispatcherInterface;
use Rougin\Slytherin\Routing\Router;

// Load the Composer autoloader ----
$root = dirname(dirname(__DIR__));

require "$root/vendor/autoload.php";
// ---------------------------------

// Define HTTP objects that is compliant to PSR-07 standards ---
$request = new ServerRequest((array) $_SERVER);

$response = new Response(http_response_code());
// -------------------------------------------------------------

// Create a new router to add an HTTP route... ---
$router = new Router;

$router->get('/', function ()
{
    return 'Hello world!';
});
// -----------------------------------------------

// ...then define it to a dispatcher ---
$dispatcher = new Dispatcher($router);
// -------------------------------------

// Add the above objects through a container ------------
$container = new Container;

$container->set(ServerRequestInterface::class, $request);

$container->set(ResponseInterface::class, $response);

$container->set(DispatcherInterface::class, $dispatcher);
// ------------------------------------------------------

// Lastly, run the application ------
(new Application($container))->run();
// ----------------------------------

Then kindly check the Running the web server section on how to run the example code above.

Using the ContainerInterface

Based on the example code above, the $container must be implemented in Rougin\Slytherin\Container\ContainerInterface:

namespace Rougin\Slytherin\Container;

use Psr\Container\ContainerInterface as PsrContainerInterface;

interface ContainerInterface extends PsrContainerInterface
{
    /**
     * Sets a new instance to the container.
     *
     * @param  string $id
     * @param  mixed  $concrete
     * @return self
     */
    public function set($id, $concrete);
}

Kindly notice that the said interface is extended to the ContainerInterface of the official PSR-11 package (psr/container) which is a common interface for dependency injection containers:

namespace Psr\Container;

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);
}

Tip

Kindly read the PSR-11 specification to understand more of its concept and how to conform on its interfaces.

The ContainerInterface is regarded as the foundation of the Slytherin package since a container must be identified with its dependencies to resolve Slytherin's required core components (e.g., HTTP, Middleware, Routing, etc.).

Third-party implementations

Slytherin also provides third-party implementations to the ContainerInterface for those who needs to use it right way and implement an improve version for the interface later. The said implementations can be found in the Container page.

Implementations under ContainerInterface

With the usage of ContainerInterface, it is possible to create alternative implementations to improve the maintainability and reusability of application code. One of its alternative implementations is the Components implementations which has its own implementation page.

← Preparing New Project | "Components" Implementation →