{"id":13622599,"url":"https://github.com/AcclimateContainer/acclimate-container","last_synced_at":"2025-04-15T09:33:09.025Z","repository":{"id":56939889,"uuid":"12638729","full_name":"AcclimateContainer/acclimate-container","owner":"AcclimateContainer","description":"Adapters for PHP framework containers to an interoperable interface","archived":false,"fork":false,"pushed_at":"2023-08-18T15:39:14.000Z","size":126,"stargazers_count":218,"open_issues_count":6,"forks_count":15,"subscribers_count":13,"default_branch":"2.x","last_synced_at":"2024-05-22T15:08:42.786Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AcclimateContainer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2013-09-06T07:44:03.000Z","updated_at":"2024-04-26T16:18:32.000Z","dependencies_parsed_at":"2022-08-21T06:50:57.534Z","dependency_job_id":null,"html_url":"https://github.com/AcclimateContainer/acclimate-container","commit_stats":{"total_commits":75,"total_committers":12,"mean_commits":6.25,"dds":0.4666666666666667,"last_synced_commit":"8c3373637900c48aa4a950bdb7099ac881d8f382"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AcclimateContainer%2Facclimate-container","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AcclimateContainer%2Facclimate-container/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AcclimateContainer%2Facclimate-container/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AcclimateContainer%2Facclimate-container/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AcclimateContainer","download_url":"https://codeload.github.com/AcclimateContainer/acclimate-container/tar.gz/refs/heads/2.x","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223668246,"owners_count":17182897,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T21:01:21.507Z","updated_at":"2024-11-08T10:30:36.483Z","avatar_url":"https://github.com/AcclimateContainer.png","language":"PHP","funding_links":[],"categories":["Table of Contents","PHP","目录"],"sub_categories":["Dependency Injection","依赖注入 Dependency Injection","Library"],"readme":"# Acclimate - Container Adapters\n\n[![License](https://poser.pugx.org/acclimate/container/license.png)](https://packagist.org/packages/acclimate/container) [![Latest Stable Version](https://poser.pugx.org/acclimate/container/v/stable.png)](https://packagist.org/packages/acclimate/container) [![Build Status](https://travis-ci.org/jeremeamia/acclimate-container.png)](https://travis-ci.org/jeremeamia/acclimate-container) [![Code Coverage](https://scrutinizer-ci.com/g/jeremeamia/acclimate-container/badges/coverage.png?s=fe11762e3c76d92ffbd4a7220e6b72c958d62b41)](https://scrutinizer-ci.com/g/jeremeamia/acclimate-container/) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/jeremeamia/acclimate-container/badges/quality-score.png?s=30cc017c8a53f50fec5b5becd7aa648930b9a1c0)](https://scrutinizer-ci.com/g/jeremeamia/acclimate-container/)\n\n**Get Acclimated!** Use any third-party dependency injection containers and service locators in your code by adapting\nthem to a common container interface. Acclimate was created by [Jeremy Lindblom](https://twitter.com/jeremeamia).\n\n## Introduction\n\nIt seems like every framework has its own container object. They come in many shapes and sizes (service locator, service\nmanager, service container, dependency injection (DI) container, registry, etc.), but are all generally used in a\nsimilar way.\n\nThe wide variety of implementations makes it hard for other frameworks, framework-agnostic libraries, or some\napplications to get the full benefits of using an inversion of control (IoC) system, because they either need to:\n\n1. Write their own container implementation (NIH Syndrome)\n2. Have a long-term dependency on a particular, third-party container implementation (and force that dependency on\n   their users, which may already be using a different container implementation)\n3. Implement an abstraction layer to support one or more third-party containers\n\n**Acclimate** is a library that does \\#3 for you. It provides a set of adapters for the most popular\ncontainer implementations. This allows you to adapt, _or \"acclimate\"_, instances of these containers to a common,\nnormalized, and **interoperable** interface. Using Acclimate allows your framework, library, or application to retrieve\nitems from the container objects of third-party libraries. That's interoperability!\n\n## The Container Interface\n\nThe `ContainerInterface` used by Acclimate comes from the\n[`psr/container`](https://github.com/php-fig/container) project. It attempts\nto normalize the various implementations of container interfaces (whether they be for service locators, dependency\ninjection containers, or something else similar) to a simple, readonly interface, that allows users to retrieve\nentries from any third-party container in a consistent way.\n\nAcclimate v1 and previous use the similar\n[`container-interop/container-interop`](https://github.com/container-interop/container-interop) standard\n\nThe `ContainerInterface` looks like this:\n\n```php\nnamespace Psr\\Container;\n\ninterface ContainerInterface\n{\n    /**\n     * @param string $id\n     * @return mixed\n     * @throws NotFoundException\n     * @throws ContainerException\n     */\n    public function get($id);\n\n    /**\n     * @param string $id\n     * @return bool\n     */\n    public function has($id);\n}\n```\n\n## Installation\n\nInstall the `acclimate/container` package using Composer. This will also also install\n`psr/container`, which provides the `ContainerInterface`.\n\n**Warning:** If you install Acclimate with dev dependencies, you will get A LOT of packages from various frameworks\n(e.g., ZF, Symfony, Laravel, etc.). These packages are *required for testing only* to ensure that all of the adapter\nclasses work correctly. They are not included when you run Composer with `--no-dev`.\n\n**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.\n\n## Basic Usage\n\n**Acclimate: Container** provides a `ContainerAcclimator` object that is used to adapt a container object to a\nnormalized `ContainerInterface`. In terms of design patterns, it's essentially a factory for adapters.\n\nHere is an example of how to use the `ContainerAcclimator`:\n\n```php\n\u003c?php\n\n// Require the Composer autoloader\nrequire 'vendor/autoload.php';\n\nuse Acclimate\\Container\\ContainerAcclimator;\n\n// Create a `Pimple` container and store an `SplQueue` object in it\n$pimple = new Pimple();\n$pimple['queue'] = function() {\n    $queue = new SplQueue();\n    $queue-\u003eenqueue('Hello!');\n    return $queue;\n};\n\n// Create a `ContainerAcclimator` and use it to adapt the `Pimple` container to the Acclimate `ContainerInterface`\n$acclimator = new ContainerAcclimator;\n$container = $acclimator-\u003eacclimate($pimple);\n\n// Use the adapted container via the common interface to fetch the queue object\n$queue = $container-\u003eget('queue');\necho $queue-\u003edequeue(); // Look! The queue object still works!\n#\u003e Hello!\n```\n\nNow you can use the container from your favorite framework and acclimate it into your other code. :-)\n\n## Container Decorators\n\nThe default behavior of a container implementing the `ContainerInterface` is to throw a\n`Psr\\Container\\NotFoundExceptionInterface` when using `get()` to retrieve an entry that does not actually exist in\nthe container. In some cases, you may want to change this default behavior to do something else instead (e.g., return\n`null`). Container decorators allow you to easily modify the behavior of a container. `acclimate\\container` ships with\n3 decorators (`NullOnMissContainer`, `CallbackOnMissContainer`, and `FailoverOnMissContainer`), but allows you to easily\ncreate your own by extending `Acclimate\\Container\\Decorator\\AbstractContainerDecorator`.\n\nHere is an example of how to use the `NullOnMissContainer` decorator:\n\n```php\n\u003c?php\n\n// Require the Composer autoloader\nrequire 'vendor/autoload.php';\n\nuse Acclimate\\Container\\ArrayContainer;\nuse Acclimate\\Container\\Decorator\\NullOnMissContainer;\nuse Psr\\Container\\NotFoundExceptionInterface;\n\n// Create an empty, basic container following the `ContainerInterface`\n$container = new ArrayContainer();\n\n// Normally, this container will throw an exception on missing items\ntry {\n    $item = $container-\u003eget('foo');\n} catch (NotFoundExceptionInterface $e) {\n    echo $e-\u003egetMessage() . \"\\n\";\n}\n# There is no entry found in the container for the identifier \"foo\".\n\n// Decorate the container so that null is returned instead of throwing an exception\n$container = new NullOnMissContainer($container);\n$item = $container-\u003eget('foo');\nvar_dump($item);\n#\u003e NULL\n```\n\n## Composite Container\n\nYou can create composite containers if your use case requires that you need to fetch data from two or more different\ncontainer objects. For the sake of the following example, we will say the you have a Symfony `Container` stored in the\nvariable `$sfContainer`, and a Zend `ServiceManager` stored in the variable `$zfContainer`.\n\n```php\nuse Acclimate\\Container\\ContainerAcclimator;\nuse Acclimate\\Container\\CompositeContainer;\n\n// First, let's acclimate these containers\n$acclimator = new ContainerAcclimator;\n$sfContainer = $acclimator-\u003eacclimate($sfContainer);\n$zfContainer = $acclimator-\u003eacclimate($zfContainer);\n\n// Now, we will put these two containers together\n$container = new CompositeContainer([$sfContainer, $zfContainer]);\n\n// When we execute the `has()` method of the container, it will return `true`\n// if at least one of these containers contains an item identified by \"foo\"\n$exists = $container-\u003ehas('foo');\n```\n\nThis is essentially a way to support container chaining, but uses the Composite design pattern instead of the Chain of\nCommand design pattern. You can also use the `FailoverOnMissContainer` decorator to support chaining.\n\n## Supported Containers\n\n* [Aura.Di Container](https://github.com/auraphp/Aura.Di/blob/develop/src/Aura/Di/ContainerInterface.php)\n* [Laravel Container](https://github.com/laravel/framework/blob/master/src/Illuminate/Container/Container.php)\n* [Nette DI Container](https://github.com/nette/nette/blob/master/Nette/DI/Container.php)\n* [PHP-DI Container](https://github.com/mnapoli/PHP-DI/blob/master/src/DI/Container.php)\n* [Pimple](https://github.com/fabpot/Pimple/blob/master/lib/Pimple.php)\n* [Symfony Dependency Injection Container](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/DependencyInjection/ContainerInterface.php)\n* [ZF2 Dependency Injection](https://github.com/zendframework/zf2/blob/master/library/Zend/Di/ServiceLocatorInterface.php)\n* [ZF2 Service Manager](https://github.com/zendframework/zf2/blob/master/library/Zend/ServiceManager/ServiceLocatorInterface.php)\n* [ZF2 Dependency Injection](https://github.com/zendframework/zf2/blob/master/library/Zend/Di/ServiceLocatorInterface.php)\n* [Phalcon DI](http://docs.phalconphp.com/en/latest/api/Phalcon_DiInterface.html)\n* Any other container-like object that implements `ArrayAccess` (see [`ArrayAccess` in the PHP Manual](http://php.net/manual/en/class.arrayaccess.php))\n\nAlso, the [Silex Application](https://github.com/fabpot/Silex/blob/master/src/Silex/Application.php) and other projects\ndescending from Pimple can be used with Acclimate as well.\n\n## Deprecated Containers\n\nSupport for the following containers is deprecated in version 1.1, and will be removed in 2.0:\n\n* [Guzzle Service Builder](https://github.com/guzzle/service/blob/master/Builder/ServiceBuilderInterface.php)\n\n### What if the Container I use is not supported?\n\n*Please consider submitting a Pull Request with an adapter for your container and a corresponding test.*\n\nBefore you get to that point though, you can create the adapter yourself (which is *really* easy to do actually, just\nlook at the included ones), and use the `ContainerAcclimator::registerAdapter()` method to wire up your adapter to\nAcclimate. You will need to provide the fully qualified class name (FQCN) of both the adapter class and the base class\nor interface of the container you want to be able to adapt (the \"adaptee\").\n\nAssuming that you have a `$container` object that implements `Your\\Favorite\\ContainerInterface`, and you have written an\nadapter class named `Your\\Favorite\\ContainerAdapter`, here is an example of how you can make these work in Acclimate:\n\n```php\nuse Acclimate\\Container\\ContainerAcclimator;\n\n// Instantiate the `ContainerAcclimator` and register your custom adapter\n$acclimator = new ContainerAcclimator;\n$acclimator-\u003eregisterAdapter('Your\\Favorite\\ContainerAdapter', 'Your\\Favorite\\ContainerInterface');\n\n// Use Acclimate to adapt your container\n$adaptedContainer = $acclimator-\u003eacclimate($container);\n```\n\n## Resources\n\n* [PSR-11 project](https://github.com/php-fig/container)\n* [Container Interop project](https://github.com/container-interop/container-interop)\n* [Service container usage comparison](https://gist.github.com/mnapoli/6159681)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAcclimateContainer%2Facclimate-container","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FAcclimateContainer%2Facclimate-container","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAcclimateContainer%2Facclimate-container/lists"}