Pedic is a Dependency Injection Container written in PHP.
PHP
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
src/Pedic
tests/PedicTest
.gitignore
LICENSE
README.rst
composer.json
phpunit.xml.dist

README.rst

Pedic

Pedic is a Dependency Injection Container written in PHP. Pedic's goal, beyond the normal Dependency Injection Container functionality you've grown to expect, is to be easy to understand. It does this by having a minimal codebase and promoting patterns that will allow your IDE to understand your code such that you get all the tooltips, autocomplete, jumping to declarations, and all the IDE candy that makes navigating a codebase easier.

More on the motivation behind Pedic can be read here: http://blog.bywires.com/articles/programming/pimple-free/

Installation

Add Pedic to your composer.json file:

$ composer require bywires/pedic

Usage

Below is a single Container with a single Factory method. Factory methods are expected to be private or protected and prefaced by an underscore. Factory methods are executed when a magic property with the same name (minus the leading underscore) are accessed. PHPDoc is used to tell your IDE about these magic properties and what type they are. This should allow your IDE to provide things like tooltips, autocomplete, jump to declarations and so on. These features go a long way in helping future readers of the code you write using Pedic.

/**
 * @property HttpDriver $httpDriver
 */
class AppContainer extends Container
{
    protected function _httpDriver()
    {
        return new CurlDriver();
    }
}

$appContainer = new AppContainer();
assert($appContainer->httpDriver instanceof HttpDriver);

With a simple tweak you can declare that the result of a Factory method is a Singleton. This means the result is reused on subsequent requests without calling your Factory method again.

/**
 * @property HttpDriver $httpDriver
 */
class AppContainer extends Container
{
    protected function _httpDriver()
    {
        return $this->singleton(new CurlDriver());
    }
}

Containers can be nested, creating a hierarchy of dependencies. Child Containers are initialized lazily and then stored by reference (a new instance of the Container is NOT created every time the corresponding attribute is accessed).

/**
 * @property ApiContainer $api
 */
class AppContainer extends Container
{
    protected function _api()
    {
        return $this->child(new ApiContainer());
    }
}

$appContainer = new AppContainer();
assert($appContainer->api instanceof ApiContainer);

Child Containers have a reference to the root Container of the Container hierarchy, so they can use other dependencies in the tree.

/**
 * @property AppContainer $rootContainer
 * @property ApiClient $client
 */
class ApiContainer extends Container
{
    protected function _client() {
        return new ApiClient($this->rootContainer->httpDriver);
    }
}

$appContainer = new AppContainer();
assert($appContainer->api->client instanceof ApiClient);

You can also set attributes to Factories or values. This is good for testing purposes, though not recommended for production because you lose all the IDE features described earlier.

$appContainer->api->client = $appContainer->factory(function(Container $container) {
    return new MockApiClient();
});

// or...

$appContainer->api->client = $appContainer->value(new MockApiClient());