Adapters for PHP framework containers to an interoperable interface

Overview

Acclimate - Container Adapters

License Latest Stable Version Build Status Code Coverage Scrutinizer Code Quality

Get Acclimated! Use any third-party dependency injection containers and service locators in your code by adapting them to a common container interface. Acclimate was created by Jeremy Lindblom.

Introduction

It seems like every framework has its own container object. They come in many shapes and sizes (service locator, service manager, service container, dependency injection (DI) container, registry, etc.), but are all generally used in a similar way.

The wide variety of implementations makes it hard for other frameworks, framework-agnostic libraries, or some applications to get the full benefits of using an inversion of control (IoC) system, because they either need to:

  1. Write their own container implementation (NIH Syndrome)
  2. Have a long-term dependency on a particular, third-party container implementation (and force that dependency on their users, which may already be using a different container implementation)
  3. Implement an abstraction layer to support one or more third-party containers

Acclimate is a library that does #3 for you. It provides a set of adapters for the most popular container implementations. This allows you to adapt, or "acclimate", instances of these containers to a common, normalized, and interoperable interface. Using Acclimate allows your framework, library, or application to retrieve items from the container objects of third-party libraries. That's interoperability!

The Container Interface

The ContainerInterface used by Acclimate comes from the psr/container project. It attempts to normalize the various implementations of container interfaces (whether they be for service locators, dependency injection containers, or something else similar) to a simple, readonly interface, that allows users to retrieve entries from any third-party container in a consistent way.

Acclimate v1 and previous use the similar container-interop/container-interop standard

The ContainerInterface looks like this:

namespace Psr\Container;

interface ContainerInterface
{
    /**
     * @param string $id
     * @return mixed
     * @throws NotFoundException
     * @throws ContainerException
     */
    public function get($id);

    /**
     * @param string $id
     * @return bool
     */
    public function has($id);
}

Installation

Install the acclimate/container package using Composer. This will also also install psr/container, which provides the ContainerInterface.

Warning: If you install Acclimate with dev dependencies, you will get A LOT of packages from various frameworks (e.g., ZF, Symfony, Laravel, etc.). These packages are required for testing only to ensure that all of the adapter classes work correctly. They are not included when you run Composer with --no-dev.

Note: We recommend using Composer and Composer's autoloader to load this library. If you are not using Composer's autoloader, be sure to use a PSR-4 compliant autoloader and map the namespace prefix Acclimate\Container\ to the src/ directory in order to correct autoload the classes.

Basic Usage

Acclimate: Container provides a ContainerAcclimator object that is used to adapt a container object to a normalized ContainerInterface. In terms of design patterns, it's essentially a factory for adapters.

Here is an example of how to use the ContainerAcclimator:

<?php

// Require the Composer autoloader
require 'vendor/autoload.php';

use Acclimate\Container\ContainerAcclimator;

// Create a `Pimple` container and store an `SplQueue` object in it
$pimple = new Pimple();
$pimple['queue'] = function() {
    $queue = new SplQueue();
    $queue->enqueue('Hello!');
    return $queue;
};

// Create a `ContainerAcclimator` and use it to adapt the `Pimple` container to the Acclimate `ContainerInterface`
$acclimator = new ContainerAcclimator;
$container = $acclimator->acclimate($pimple);

// Use the adapted container via the common interface to fetch the queue object
$queue = $container->get('queue');
echo $queue->dequeue(); // Look! The queue object still works!
#> Hello!

Now you can use the container from your favorite framework and acclimate it into your other code. :-)

Container Decorators

The default behavior of a container implementing the ContainerInterface is to throw a Psr\Container\NotFoundExceptionInterface when using get() to retrieve an entry that does not actually exist in the container. In some cases, you may want to change this default behavior to do something else instead (e.g., return null). Container decorators allow you to easily modify the behavior of a container. acclimate\container ships with 3 decorators (NullOnMissContainer, CallbackOnMissContainer, and FailoverOnMissContainer), but allows you to easily create your own by extending Acclimate\Container\Decorator\AbstractContainerDecorator.

Here is an example of how to use the NullOnMissContainer decorator:

<?php

// Require the Composer autoloader
require 'vendor/autoload.php';

use Acclimate\Container\ArrayContainer;
use Acclimate\Container\Decorator\NullOnMissContainer;
use Psr\Container\NotFoundExceptionInterface;

// Create an empty, basic container following the `ContainerInterface`
$container = new ArrayContainer();

// Normally, this container will throw an exception on missing items
try {
    $item = $container->get('foo');
} catch (NotFoundExceptionInterface $e) {
    echo $e->getMessage() . "\n";
}
# There is no entry found in the container for the identifier "foo".

// Decorate the container so that null is returned instead of throwing an exception
$container = new NullOnMissContainer($container);
$item = $container->get('foo');
var_dump($item);
#> NULL

Composite Container

You can create composite containers if your use case requires that you need to fetch data from two or more different container objects. For the sake of the following example, we will say the you have a Symfony Container stored in the variable $sfContainer, and a Zend ServiceManager stored in the variable $zfContainer.

use Acclimate\Container\ContainerAcclimator;
use Acclimate\Container\CompositeContainer;

// First, let's acclimate these containers
$acclimator = new ContainerAcclimator;
$sfContainer = $acclimator->acclimate($sfContainer);
$zfContainer = $acclimator->acclimate($zfContainer);

// Now, we will put these two containers together
$container = new CompositeContainer([$sfContainer, $zfContainer]);

// When we execute the `has()` method of the container, it will return `true`
// if at least one of these containers contains an item identified by "foo"
$exists = $container->has('foo');

This is essentially a way to support container chaining, but uses the Composite design pattern instead of the Chain of Command design pattern. You can also use the FailoverOnMissContainer decorator to support chaining.

Supported Containers

Also, the Silex Application and other projects descending from Pimple can be used with Acclimate as well.

Deprecated Containers

Support for the following containers is deprecated in version 1.1, and will be removed in 2.0:

What if the Container I use is not supported?

Please consider submitting a Pull Request with an adapter for your container and a corresponding test.

Before you get to that point though, you can create the adapter yourself (which is really easy to do actually, just look at the included ones), and use the ContainerAcclimator::registerAdapter() method to wire up your adapter to Acclimate. You will need to provide the fully qualified class name (FQCN) of both the adapter class and the base class or interface of the container you want to be able to adapt (the "adaptee").

Assuming that you have a $container object that implements Your\Favorite\ContainerInterface, and you have written an adapter class named Your\Favorite\ContainerAdapter, here is an example of how you can make these work in Acclimate:

use Acclimate\Container\ContainerAcclimator;

// Instantiate the `ContainerAcclimator` and register your custom adapter
$acclimator = new ContainerAcclimator;
$acclimator->registerAdapter('Your\Favorite\ContainerAdapter', 'Your\Favorite\ContainerInterface');

// Use Acclimate to adapt your container
$adaptedContainer = $acclimator->acclimate($container);

Resources

Comments
  • Request for Feedback

    Request for Feedback

    What do you think about Acclimate? Is it a good idea? Can you think of any good use cases for it? Any other thoughts, ideas, feedback, criticism, or praise you want to share? Please do.

    discuss 
    opened by jeremeamia 18
  • Change the vendor name

    Change the vendor name

    After a discussion with @dongilbert on Twitter, it might make sense to change the vendor name and namespace/directory structure of Acclimate to:

    1. Broaden the potential scope of Acclimate (which is a cool name) so that other types of adapters could be created (e.g., event dispatching, session handling, etc.).
    2. Not be directly associated with my name in the case that the project is passed on to another owner at some point.

    This is all pending some more positive feedback/support and evidence of usefulness of the package itself, so I can justify spending time and effort on it. Changing the namespaces would happen before the 1.0 release.

    • Current:
      • Package Namespace: Jeremeamia\Acclimate
      • Core Class: Jeremeamia\Acclimate\Acclimate
    • Proposed:
      • Package Namespace: Acclimate\Container?
      • Core Class: Acclimate\Container\ContainerAcclimator?
    idea 
    opened by jeremeamia 8
  • Namespace -> dir mapping inconsistent (PSR4 compliance)?

    Namespace -> dir mapping inconsistent (PSR4 compliance)?

    (Apologies in advance if this is some noob error on my part)

    EXPECTED: PSR4 compliance? namespace Acclimate\Container; should be found at: acclimate-container/src/Acclimate/Container/

    ACTUAL: namespace Acclimate\Container; Is found at: acclimate-container/src/`

    Notes

    Acclimate doesn't seem consistent with PSR4 (http://www.php-fig.org/psr/psr-4/) :

    "The contiguous sub-namespace names after the "namespace prefix" correspond to a subdirectory within a "base directory", in which the namespace separators represent directory separators. The subdirectory name MUST match the case of the sub-namespace names."

    Other projects, even the PHP DI interop, map more directly and consistently, for example: container-interop/src/Interop/Container/ContainerInterface.php

    //
    namespace Interop\Container;
    
    interface ContainerInterface
    {
    

    I'm not using (and can't use) composer, so perhaps that's why It's affected me?

    (PS: Thanks for making and maintaining this library, very useful!)

    opened by woodywould 6
  • Added Phalcon DI Container Adapter

    Added Phalcon DI Container Adapter

    One issue in this commit is, that as Phalcon cannot be just installed using composer, as it needs to be compiled, I made the tests skippable if phalcon is not present using the following comment

    /**
     * @requires extension phalcon
     */
    

    That produces three S (skipped) in the command line test runner. I have not found a nicer method.

    opened by theluk 6
  • Consider separating container from adaptors

    Consider separating container from adaptors

    Any chance you would consider breaking this into two projects, one for the container implementation and one for the adaptors (or even one per adaptor). I would love to use this project as a central DI container for a micro-framework project, but having to load all the dev dependencies for any dev project when using the micro-framework is a problem we would like to avoid. Users who want to take advantage of adaptors to other containers may not mind the extra weight, but the burden should not be placed on all users of the container.

    opened by opengeek 5
  • Use native Pimple PSR-11 Container adapter

    Use native Pimple PSR-11 Container adapter

    As Pimple now has it's own built-in adapter, it would make sense for Acclimate to simply use that one and then it's one less adapter to have to keep up to date.

    opened by shrikeh 3
  • Added the possibility to create a container chain

    Added the possibility to create a container chain

    This similar to a composite container, but uses a chain-of-reponsibility pattern to implement composition. Why? The main benefit is that it's not using iteration to find the container responsible for the given id. The chain is also able to replace the FailoverOnMissContainer if has() works as expected. Using exceptions for for control flow is an anti-pattern.

    opened by hoesler 3
  • Add static constructor for acclimator

    Add static constructor for acclimator

    I found that once I had registered my given framework's DI implementation with Acclimate, I didn't need the acclimator that often afterward, and also during testing, where it was just another step in setup. I found myself pining for 'Acclimator::doYourThing($pimple)` and just getting back the adapted DI.

    opened by shrikeh 2
  • Phalcon

    Phalcon

    Rival to PR https://github.com/jeremeamia/acclimate-container/pull/10 , which seems to have been abandonned. Took commits from #10, and ran coding standards fixer.

    opened by Sam-Burns 2
  • Adding delegate-lookup support to ArrayContainer

    Adding delegate-lookup support to ArrayContainer

    Hi Jeremy,

    Following the release of container-interop 1.1 that adds the delegate-lookup feature, I just stumbled on your ArrayContainer class and could not resist the temptation to add support for this feature in your class.

    Quite simple really. Hope you will like it and accept this pull request :) Ho, and unit tests are here too!

    opened by moufmouf 2
  • make() method?

    make() method?

    Hey, thanks for a great tool! I'm trying to integrate PHP DI and larval containers.

    This is specifically because Laravel's container has some funky behaviour and from my usage, it seems inferior to PHP DI.

    I understand that a make method is outside of the scope of PSR11, but seems like a useful addition to Acclimate?

    http://php-di.org/doc/container.html#make https://laravel.com/docs/5.5/container#resolving

    opened by lougreenwood 1
Releases(2.0.0)
  • 2.0.0(Jun 15, 2017)

    • Switching from the now-deprecated Container-Interop standard to FIG's PSR-11.
    • Removes support for obsolete versions of the Guzzle curl library's container.
    • Drops support for PHP 5.5 and previous.
    Source code(tar.gz)
    Source code(zip)
  • 1.1.0(Apr 29, 2017)

  • 1.0.0(Mar 19, 2014)

    Acclimate is now stable and generally available.

    • Added Travis and Scrutinizer configs and badges
    • Fixed the Nette adapter tests to not use deprecated features
    • Moved the adapter map from ContainerAcclimator.php to it's own file: Adapter/map.php
    • Minor updates to other tests
    • Updates to README and various docblocks
    • Removed suggests from composer.json because it creates a lot of meaningless noise
    Source code(tar.gz)
    Source code(zip)
  • 1.0.0-rc.1(Mar 18, 2014)

    Almost there!

    • Adopted the container-interop project's ContainerInterface
    • Removed the acclimate/api dependency
    • Updated PSR-4 support
    • Added the FailoverOnMissDecorator
    • Now differentiating between NotFoundExceptions and the more general ContainerExceptions
    • General code and docblock cleanup

    Please review and provide feedback in preparation of the stable 1.0.0 release.

    Source code(tar.gz)
    Source code(zip)
  • 0.3.0(Dec 18, 2013)

    Big Changes!

    • Renamed the namespace to Acclimate\Container
    • Renamed the Packagist/Composer package to acclimate/container
    • Factored out the ContainerInterface into a separate package
    • Converted the package structure to PSR-4 style
    Source code(tar.gz)
    Source code(zip)
  • 0.2.0(Oct 15, 2013)

  • 0.1.0(Sep 25, 2013)

    This is the beta release of Acclimate. This release includes the following features:

    • Simple, readonly, service container interface
    • Simple, concrete ArrayContainer implementation
    • Container adapters for:
      • Aura
      • Guzzle
      • Laravel
      • Pimple & Silex
      • Symfony
      • Zend Framework (Service Manager & Dependency Injection)
      • Any other container that implements ArrayAccess
    • A CompositeContainer that allows you to combine containers
    • Container decorators for modifying the behavior of container misses
    Source code(tar.gz)
    Source code(zip)
Owner
Acclimate Container
The Acclimate Container project - unifying dependency injection containers in PHP
Acclimate Container
ServiceManager component from Zend Framework

zend-servicemanager Repository abandoned 2019-12-31 This repository has moved to laminas/laminas-servicemanager. Master: Develop: The Service Locator

Zend Framework 192 Nov 21, 2022
A small PHP dependency injection container

Pimple Caution! Pimple is now closed for changes. No new features will be added and no cosmetic changes will be accepted either. The only accepted cha

Silex 2.6k Dec 29, 2022
💎 Flexible, compiled and full-featured Dependency Injection Container with perfectly usable autowiring and support for all new PHP 7 features.

Nette Dependency Injection (DI) Introduction Purpose of the Dependecy Injection (DI) is to free classes from the responsibility for obtaining objects

Nette Foundation 781 Dec 15, 2022
PSR-11 compatible Dependency Injection Container for PHP.

bitexpert/disco This package provides a PSR-11 compatible, annotation-based dependency injection container. Have a look at the disco-demos project to

bitExpert AG 137 Sep 29, 2022
🚀 PHP Service Container with fast and cachable dependency injection.

ClanCats Container A PHP Service Container featuring a simple meta-language with fast and compilable dependency injection. Requires PHP >= 7.0 Pros: M

ClanCats 28 Apr 13, 2022
Dependency Manager for PHP

Composer - Dependency Management for PHP Composer helps you declare, manage, and install dependencies of PHP projects. See https://getcomposer.org/ fo

Composer 27.2k Dec 31, 2022
Twittee is the smallest, and still useful, Dependency Injection Container in PHP

What is Twittee? Twittee is the smallest, and still useful, Dependency Injection Container in PHP; it is also probably one of the first public softwar

null 133 Dec 5, 2022
Adapters for PHP framework containers to an interoperable interface

Get Acclimated! Use any third-party dependency injection containers and service locators in your code by adapting them to a common container interface.

Acclimate Container 215 Dec 16, 2022
Incubator adapters/functionality for the Phalcon PHP Framework

Phalcon Incubator This is a repository to publish/share/experiment with new adapters, prototypes or functionality that can potentially be incorporated

The Phalcon PHP Framework 735 Dec 27, 2022
PHP cache library, with adapters for e.g. Memcached, Redis, Couchbase, APC(u), SQL and additional capabilities (e.g. transactions, stampede protection) built on top.

Donate/Support: Documentation: https://www.scrapbook.cash - API reference: https://docs.scrapbook.cash Table of contents Installation & usage Adapters

Matthias Mullie 295 Nov 28, 2022
A simple cache library. Implements different adapters that you can use and change easily by a manager or similar.

Desarolla2 Cache A simple cache library, implementing the PSR-16 standard using immutable objects. Caching is typically used throughout an applicatito

Daniel González 129 Nov 20, 2022
A simple cache library. Implements different adapters that you can use and change easily by a manager or similar.

Desarolla2 Cache A simple cache library, implementing the PSR-16 standard using immutable objects. Caching is typically used throughout an applicatito

Daniel González 129 Nov 20, 2022
Symfony 5.2 + api platform project with ELK stack + elastic FileBeats for the log management. All running in 7 docker containers: nginx, php 8, mysql, elastic search, logstash, kibana, fileBeats.

Symfony with ELK and Elastic FileBeats Stack Prerequisites: Make sure that docker and docker-compose are installed in your machine and available for y

null 13 May 20, 2022
Easily install PHP extension in Docker containers

Easy installation of PHP extensions in official PHP Docker images This repository contains a script that can be used to easily install a PHP extension

Michele Locati 2.8k Jan 4, 2023
Nuber is an open source container management platform it provides a front end to manage your own cloud infrastructure, using Linux Containers virtualization technology

Nuber is an open source container management platform it provides a front end to manage your own cloud infrastructure, using Linux Containers virtualization technology

null 33 Dec 14, 2022
Docker Containers for simple Laravel development.

Docker containers of Laravel development. Docker Containers for simple Laravel development. Prerequisites This package only works for Linux users righ

Steve Azzopardi 14 May 19, 2022
A complete stack for running Symfony 5 into Docker containers using docker-compose tool and with Certbot for the HTTPS certificate.

?? Docker + PHP 7.4 + MySQL8.0 + Nginx + Certbot(HTTPS) + Symfony 5 Boilerplate ?? Edited from https://github.com/ger86/symfony-docker version -> http

null 6 Nov 9, 2022
Takeout is a CLI tool for spinning up tiny Docker containers, one for each of your development environment dependencies.

Takeout Takeout is a CLI tool for spinning up tiny Docker containers, one for each of your development environment dependencies. It's meant to be pair

Tighten 1.4k Jan 2, 2023
Docker-magento2 - 🐳 Docker containers with all required Magento 2 dependencies installed available as FPM through Nginx and CLI

Magento 2 Docker A collection of Docker images for running Magento 2 through nginx and on the command line. Quick Start cp composer.env.sample compose

Meanbee 454 Dec 27, 2022
A Magento Development Environment Made of Docker Containers

Docker for Magento 1 Extension Development Tl;dr How do I use this? Clone it. Type docker-compose up -d. Install a Magento Mount your file share. Deve

Michael A. Smith 99 May 10, 2021