{"id":22092107,"url":"https://github.com/krakphp/cargo","last_synced_at":"2025-03-23T23:44:57.562Z","repository":{"id":57009023,"uuid":"80394121","full_name":"krakphp/cargo","owner":"krakphp","description":"Lightweight container library with powerful design and pimple compatibility","archived":false,"fork":false,"pushed_at":"2018-02-12T23:48:08.000Z","size":614,"stargazers_count":2,"open_issues_count":5,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-04T01:37:38.029Z","etag":null,"topics":["cargo","container-interop","dependency-injection","ioc","psr-11","service-locator"],"latest_commit_sha":null,"homepage":null,"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/krakphp.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-01-30T04:41:43.000Z","updated_at":"2017-11-04T06:15:05.000Z","dependencies_parsed_at":"2022-08-21T13:10:47.979Z","dependency_job_id":null,"html_url":"https://github.com/krakphp/cargo","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krakphp%2Fcargo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krakphp%2Fcargo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krakphp%2Fcargo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/krakphp%2Fcargo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/krakphp","download_url":"https://codeload.github.com/krakphp/cargo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245186925,"owners_count":20574554,"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":["cargo","container-interop","dependency-injection","ioc","psr-11","service-locator"],"created_at":"2024-12-01T03:08:20.658Z","updated_at":"2025-03-23T23:44:57.532Z","avatar_url":"https://github.com/krakphp.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Cargo\n\nCargo is yet another container library. Its feature set and semantics closely follow [Pimple](http://pimple.sensiolabs.org); however, it's design is more modular so that it can be extended. It was designed to be compatible with Pimple; so you can easily use any Pimple service providers with Cargo.\n\nPimple is a great service container; however it suffers from one problem... extendability. Pimple was never designed to properly extended or decorated which makes it very hard to add features without modifying the core. Cargo is a container that manages to keep the simplicity of Pimple while allowing powerful extensions.\n\n## Installation\n\nInstall with composer at `krak/cargo`\n\n## Usage\n\n### Creating a Container\n\nThere are several ways to create cargo containers. The easiest way is to just create the default container like so:\n\n```php\n\u003c?php\n\nuse Krak\\Cargo;\n\n$c = Cargo\\container();\n```\n\nWhich is just the same as doing:\n\n```php\n$c = new Container\\BoxContainer();\n$c = new Container\\SingletonContainer($c);\n$c = new Container\\BoxFactoryContainer($c);\n$c = new Container\\FreezingContainer($c);\n$c = new Container\\AliasContainer($c);\n```\n\nCargo is designed to be extendable and flexible, so each container decorator adds a feature that can be removed if not desired.\n\nIf you want just a bare bones container, you can use the following:\n\n```php\n\u003c?php\n\n$c = Cargo\\liteContainer($values = [], $box_container = null);\n```\n\nThis just implements the Box and BoxFactory container which caches services as singletons by default.\n\n### Defining Services\n\nServices can defined and configured several ways.\n\n```php\n$c['a'] = function($c) {\n    return new ServiceA();\n};\n// or\n$c-\u003eadd('b', function($c) {\n    return new ServiceB($c['a']);\n});\n```\n\nDue to the BoxFactoryContainer, all Closures are treated as lazy services. Meaning, they are not invoked until needed. The Singleton container also defaults all services to be singletons, so the result of the service definition closure is cached so that it's not invoked twice. These semantics mimic the behavior of the [Pimple Container](http://pimple.sensiolabs.org);\n\n### Accessing the Container\n\nYou can either use the ArrayAccess methods or `get` to retrieve values and invoke services.\n\n```\n$c['a'] == $c-\u003eget('a');\n```\n\n### Factory or Singleton Services\n\nYou can specify if you want to define a service as a factory or singleton with these two helper methods.\n\n```php\n$c-\u003esingleton('a', function() {\n    return new ServiceA();\n});\n$c-\u003efactory('b', function() {\n    return new ServiceB();\n});\n// $c['a'] === $c['a'] - same instance each time\n// $c['b'] !== $c['b'] - different instance each time\n```\n\n### Parameters/Values\n\nAnything added to the container that isn't a service is defined as value.\n\n```php\n$c['a.parameter'] = 'value';\n$c['a'] = function($c) {\n    return new ServiceA($c['a.parameter']);\n};\n```\n\nValues are stored and retrieved as is. No processing is done to them.\n\nIf you want to use a closure as a parameter, you can use the `protect` method:\n\n```php\n$func = function() {};\n$c-\u003eprotect('a.closure_parameter', $func);\n// it returns the same instance because values are just stored as is.\n// $c['a.closure_parameter'] === $func\n```\n\n### Env Parameters\n\nYou can register parameters to be read from the environment with the `env` method:\n\n```php\n$c-\u003eenv('APP_KEY', $alias = 'application.key');\n// $c['APP_KEY'] === $c['application.key'] are read from the env\n```\n\n### Wrapping Services\n\nSimilar to Pimple's `extend`, Cargo allows you to wrap service definitions for decoration.\n\nIf you want to replace a definition, you would simply redefine it; however, if you want to decorate or modify a definition, you wrap it:\n\n```php\n$c['logger'] = function() {\n    return new Logger();\n};\n$c-\u003ewrap('logger', function($logger, $c) {\n    $logger-\u003esetValue($c['value']);\n    return new MyLogger($logger);\n});\n// $c['logger'] instanceof MyLogger == true\n```\n\n### Service Freezing\n\nServices by default will be frozen due to the FreezingContainer. You can redefine entries as much you'd like, but once a service is invoked, it is considered frozen and will throw an exception if you try to redefine it.\n\n```php\n$c['a'] = function() {};\n// ok to redefine because we haven't invoked 'a' yet.\n$c['a'] = function() {};\n$service = $c['a'];\n// this will throw an exception because the service was frozen\n$c['a'] = function() {};\n```\n\n### Aliasing Entries\n\nIt's often useful to use class names as the identifier, but then also provide aliases for a quick reference.\n\n```php\n$c[Acme\\ServiceA::class] = function() {\n    return new Acme\\ServiceA();\n};\n$c-\u003ealias(Acme\\ServiceA::class, 'acme.service_a', 'a');\n// $c[Acme\\ServiceA::class] === $c['service_a'] === $c['a']\n```\n\n### Auto Wiring\n\nAuto wiring allows the container to try and automatically instantiate services if they aren't already defined in the container. To enable auto-wiring, you need to:\n\n1. Install the [Auto Args](https://github.com/krakphp/auto-args) Library (`composer install krak/auto-args`)\n2. Use the AutoWireContainer\n\n```php\n// the second parameter as true will include the auto wiring\n$c = Cargo\\container([], $auto_wire = true);\n$stack = $c-\u003eget('SplStack');\n// will return an instance of SplStack as a singleton.\n\n// defines 'StdClass' as a factory instance and will set it up for auto-wiring since no definition was given.\n$c-\u003efactory('StdClass');\n// $c['StdClass'] !== $c['StdClass']\n```\n\nIn addition, you can bind any class to be auto wired:\n\n```php\n$c-\u003esingleton('a', SplStack::class);\n$c-\u003efactory('b', ArrayObject::class);\n```\n\n`a` and `b` will resolve to their respective classes. This only works on singleton/factory entries, else it'll just treat the service like a string value and won't try to auto-resolve it.\n\n### Service Providers\n\n`Cargo\\ServiceProvider` provides a simple interface for defining multiple related services.\n\n```php\ninterface ServiceProvider {\n    public function register(Cargo\\Container $c);\n}\n```\n\nYou can register service providers with a given container with the `register` method:\n\n```php\n$c-\u003eregister(new FooProvider(), [\n    'foo.parameters' =\u003e 1,\n]); // or Cargo\\register($c, new FooProvider(), [])\n```\n\n### Container Interop\n\n`Krak\\Cargo\\Container` is not compatible with the `ContainerInterop` interface by default. However, you can easily export the container to an Interop container using the `toInterop` function.\n\n```php\n$interop = Cargo\\toInterop($c); // or $c-\u003etoInterop\n// $interop instanceof Psr\\Container\\ContainerInterface\n```\n\n### Pimple Interop\n\nAchieving Pimple compatibility is simple with the `toPimple` function.\n\n```php\n$pimple = Cargo\\toPimple($c); // or $c-\u003etoPimple()\n\n$pimple['a'] = function() {};\n$pimple-\u003eextend('a', function() {});\n$pimple['b'] = $pimple-\u003eprotect(function() {\n\n});\n\n// $c has access to all services defined in pimple\n$c['b'];\n```\n\n### Delegate Containers\n\nIn an effort to provide better integration with other containers, we provide delegate containers to allow you to default to a cargo definitions, but fallback to the delegate container.\n\n`ArrayAccessDelegateContainer` and `PsrDelegateContainer` both act as delegate containers. The first will accept any array or `ArrayAccess` object (like Pimple), and the other will accept any Psr Container.\n\n```php\n\u003c?php\n\n$pimple = new Pimple\\Container();\n$pimple['a'] = 1;\n$pimple['b'] = 1;\n$c = Cargo\\container();\n$c = new Cargo\\Container\\ArrayAccessDelegateContainer($c, $pimple);\n$c['b'] = 2;\n\nassert($c['b'] == 2 \u0026\u0026 $c['a'] == 1);\n```\n\n## Cargo Design\n\n### Container Interface for Decoration\n\nTo do...\n\n### Boxes\n\nTo do...\n\n## API\n\n### function alias(Container $c, $id, ...$aliases)\n\nAliases an entry `$id` into `$aliases` for the container `$c`. Each alias will share the same box reference as the original entry.\n\n### function env(Container $c, $var_name, $id = null)\n\nAdds an EnvBox entry into the container `$c` with `$var_name` being the name of the env var and `$id` is the entry name.\nIf `$id` is left null, then it will default to `$var_name`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkrakphp%2Fcargo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkrakphp%2Fcargo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkrakphp%2Fcargo/lists"}