PHPackages                             lexide/syringe - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. lexide/syringe

ActiveLibrary

lexide/syringe
==============

Lexide Syringe, configuration utility for Pimple

2.2.6(4y ago)016.1k↑38.5%1[6 issues](https://github.com/lexide/syringe/issues)2MITPHPPHP &gt;=5.6CI failing

Since Nov 10Pushed 4y ago2 watchersCompare

[ Source](https://github.com/lexide/syringe)[ Packagist](https://packagist.org/packages/lexide/syringe)[ Docs](https://github.com/lexide/syringe)[ RSS](/packages/lexide-syringe/feed)WikiDiscussions develop Synced 1mo ago

READMEChangelog (1)Dependencies (4)Versions (55)Used By (2)

Syringe allows a [Pimple](https://github.com/silexphp/pimple) DI container to be created and populated with services defined in configuration files, in the same fashion as Symfony's [DI module](https://github.com/symfony/dependency-injection).

Installation
============

[](#installation)

`composer require lexide/syringe`

Getting Started
===============

[](#getting-started)

The simplest method to create and set up a new Container is to use the `Lexide\Syringe\Syringe` class. It requires the path to the application directory and a list of filepaths that are relative to that directory

```
use Lexide\Syringe\Syringe;

$appDir = __DIR__;
$configFiles = [
    "config/syringe.yml" // add paths to your configuration files here
];

Syringe::init($appDir, $configFiles);
$container = Syringe::createContainer();
```

Configuration Files
===================

[](#configuration-files)

By default, Syringe allows config files to be in JSON or YAML format. Each file can define parameters, services and tags to inject into the container, and these entities can be referenced in other areas of configuration.

Parameters
----------

[](#parameters)

A Parameter is a named, static value, that can be accessed directly from the Container, or injected into other parameters or services. For a config file to define a parameter, it uses the `parameters` key and then states the parameters name and value.

```
parameters:
    myParam: "value"
```

Once defined, a parameter can be referenced inside a string value by surrounding its name with the `%` symbol and the parameters value will the be inserted when the the string value is resolved. This can be done in service arguments or in other parameters, like so:

```
parameters:
    firstName: "Joe"
    lastName: "Bloggs"
    fullName: "%firstName% %lastName%"
```

Parameters can have any scalar or array value. Arrays are resolved recursively; you can set an array of strings to a parameter, each of which contain references to other parameters. This works for both values and array keys.

```
parameters:
    myFirstValue: "first"
    mySecondValue: "second"

    myList:
        - "The first value is %myFirstValue%"
        - "The second value is %mySecondValue%

    myHash:
        "%myFirstValue%": "%mySecondValue%"
```

Constants
---------

[](#constants)

Quite often, a value set in a PHP constant is required to be injected. Hard coding these value directly into DI config is brittle and requires maintenance to keep in sync, which should be avoided where possible. Syringe solves this problem by allowing PHP constants to be referenced directly in config, by surrounding the constant name with `^` characters:

```
parameters:
    maxIntValue: "^PHP_INT_MAX^"
    custom: "^MY_CUSTOM_CONSTANT^"
    classConstant: "^MyModule\\MyService::CLASS_CONSTANT^"
```

Where class constants are used, you are required to provide the fully qualified class name. As this has to be enclosed inside a string, all forward slashes must be escaped, as in the example.

Services
--------

[](#services)

Services are instances of a class that can have other services, parameters or values injected into them. A config file defines services inside the `services` key and gives each entry a `class` key, containing the fully qualified class name to instantiate. For classes which have constructor arguments, these can be specified by setting the `arguments` key to a list of values, parameters or other services, as required by the constructor

```
services:
    myService:
        class: MyModule\MyService
        arguments:
            - "first constructor argument"
            - 12345
            - false
```

### Service injection

[](#service-injection)

Services can have parameters or other services injected into them as method arguments, by referencing a service name prefixed with the `@` character. This is done in one of two ways:

#### Constructor injection

[](#constructor-injection)

Injection can be done when a service is instantiated, by setting references in `arguments` key of a service definition. This is typically done for dependencies which are required.

```
services:
    injectable:
        class: MyModule\MyDependency

    myService:
        class: MyModule\MyService
        arguments:
            - "@injectable"
            - "%myParam%"
```

#### Setter injection

[](#setter-injection)

Services can also be injected by calling a method after the service has been instantiated, passing the dependant service in as an argument. This form is useful for optional dependencies.

```
services:
    injectable:
        class: MyModule\MyDependency

    myService:
        class: MyModule\MyService
        calls:
            -
                method: "setInjectable"
                arguments:
                    - "@injectable"
```

The `calls` key can be used to run any method on a service, not necessarily one to inject a dependency. They are executed in the order they are defined.

```
services:
    myService:
        class: MyModule\MyService
        calls:
            - method: "warmCache"
            - method: "setTimeout"
              arguments: ["%myTimeout%"]
            - method: "setLogger"
              arguments: ["@myLogger"]
```

### Tags

[](#tags)

In some cases, you may want to inject all the services of a given type as a method argument. This can be done manually, by building a list of service references in config, but maintaining such a list is cumbersome and time consuming.

The solution is tags; allowing you to tag a service as being part of a collection and then to inject the whole collection of services in one reference.

A tag is referenced by prefixing its name with the `#` character.

```
services:
    logHandler1:
        ...
        tags:
            - "logHandlers"

    logHandler2:
        ...
        tags:
            - "logHandlers"

    loggerService:
        ...
        arguments:
            - "#logHandlers"
```

When the tag is resolved, the collection is passed through as a simple numeric array. The parent service will have no knowledge that a tag was used to generate this list.

### Factories

[](#factories)

If you have a number of services to be available that use the same class or interface, it can be advantageous to abstract the creation of these services into a factory class, to aid maintenance and reusability. Syringe provides two methods of using factories in this way; via a call to a static method on the factory class, or by calling a method on a separate factory service.

```
services:
    newService1:
        class: MyModule\MyService
        factoryClass: MyModule\MyServiceFactory
        factoryMethod: "createdWithStatic"

    newService2:
        class: MyModule\MyService
        factoryService: "@myServiceFactory"
        factoryMethod: "createdWithService"

    myServiceFactory:
        class: MyModule\MyServiceFactory
```

If the factory methods require arguments, you can pass them through using the `arguments` key, in the same way you would for a normal service or a method call.

### Service Aliases

[](#service-aliases)

Syringe allows you to alias a service name to point to another definition, using the `aliasOf` key. This is useful if you deal with other modules and need to use your own version of a service instead of the module's default one.

```
# [foo.yml]
services:
    default:
        class: MyModule\DefaultService
        ...

# [bar.yml]
services:
    default:
        aliasOf: "@custom"

    custom:
        class: MyModule\MyService
        ...
```

### Abstract Services

[](#abstract-services)

Services can often have definitions that are very similar or contain portions that will always be the same. As a method to reduce duplicated config, a service's definition can "extend" a base definition. This has the effect of merging the two definitions together. Any key conflicts take the service's value rather than the one from the base, however the list of calls is merged rather than overwritten. There is no restriction on what keys you can define in the base definition. Base definitions have to be marked as `abstract` and cannot be used directly as a service. These abstract definitions can extend other definitions in the same way, similar to how inheritence works in OOP.

```
services:
    loggable:
        abstract: true
        calls:
            - method: "setLogger"
            - arguments: "@logger"

    myService:
        class: MyModule\MyService
        extends: "@loggable"            # this will import the "setLogger" call into this service definition

    factoriedService:
        abstract: true
        extends: "@loggable"
        factoryClass: MyModule\MyServiceFactory
        factoryMethod: "create"

    myFactoriedService:
        class: MyModule\MyService
        extends: "@factoriedService"    # imports both the factory config and the "setLogger" call
```

### Private Services

[](#private-services)

For the vast majority of cases, there is no issue with services being accessed from outside of the current module. In fact this is advantageous as it promotes modular design, reuse of services and code discovery. However, there can be times when data security requires that a service be locked down and to not be available to anything outside of the control of the current module. Services can be marked as private by adding the `private` key to their definition:

```
services:
    myService:
        ...
        private: true
```

Private services will only be available to other services that are defined with the same config alias, usually within the same module.

### Stubbed Services

[](#stubbed-services)

In some cases, you may require an application or external library to inject a service that you don't have information on, such as a plugin or adapter that has functionality that doesn't belong in your library.

In order for syringe to handle these situations, you should create a stub service to act as a placeholder which can be aliased later. These serve as a hook or API for other libraries to interact with your code through Syringe.

```
# library A
services:

    # This service uses the "adapterService" stub
    aService:
        ...
        arguments:
            - "@adapterService"

    adapterService:
        stub: true

# library B
services:

    myAdapter:
        ...

    # alias "myAdapter" to be the service injected into "library_a.aService"
    library_a.adapterService:
        aliasOf: "@myAdapter"

```

By themselves, stub services cannot be accessed or injected; they must have been aliased before the service that uses them can be created.

Imports
-------

[](#imports)

When your object graph becomes large enough, it is often useful to split your configuration into separate files; keeping related parameters and services together. This can be done by using the `imports` key:

```
imports:
    - "loggers.yml"
    - "users.yml"
    - "report/orders.yml"
    - "report/products.yml"

services:
    ...
```

If any imported files contain duplicated keys, the file that is further down the list wins. As the parent file is always processed last, its services and parameters always take precedence over the imported config.

```
# [foo.yml]
parameters:
    baz: "from foo"

# [bar.yml]
imports:
    - "foo.yml"

parameters:
    baz: "from bar"

# when bar.yml is loaded into Syringe, the "baz" parameter will have a value of "from bar"
```

Environment Variables
---------------------

[](#environment-variables)

If required, Syringe allows you to set environment variables on the server that will be imported at runtime. This can be used to set different parameter values for local development machines and production servers, for example. Any environment variable prefixed with `SYRINGE__` will be imported as a parameter:

Config Aliases and Namespacing
------------------------------

[](#config-aliases-and-namespacing)

When dealing with a large object graph, conflicting service names can become an issue. To avoid this, Syringe allows you to set an "alias" or namespace for a config file. Within the file, services can be referenced as normal, but files which use different aliases or no alias need to prefix the service name with the alias. This allows you to compartmentalise your DI config for better organisation and to promote modular coding.

For example, the two config files, `foo.yml` and `bar.yml` can be given aliases when setting up the config files to create a Container from:

```
$configFiles = [
  "foo_alias" => "foo.yml",
  "bar_alias" => "bar.yml"
];
```

`foo.yml` could defined a service, `fooOne`, which injected another service in the same file, `fooTwo`, as normal. However, if a service in `bar.yml` wanted to inject `fooTwo`, it would have to use its full service reference `@foo_alias.fooTwo`. Likewise if `fooOne` wanted to inject `barOne` from `bar.yml` it would have to use `@bar_alias.barOne` as the service reference.

Extensions
----------

[](#extensions)

There can be times where you need to call setters on a dependent module's services, in order to inject your own dependent service as a replacement for the module's default one. In order to do this, you need to use the `extensions` key. This allows you to specify the service and provide a list of calls to make on it, essentially appending them to the service's own `calls` key

```
# [foo.yml, aliased with "foo_alias"]
services:
    myService:
        class: MyModule\MyService
        ...

# [bar.yml]
services:
    myCustomLogger:
        ...

extensions:
    foo_alias.myService:
        - method: "addLogger"
          arguments: "@myCustomLogger"
```

Reference characters
--------------------

[](#reference-characters)

In order to identify references, the following characters are used:

- `@` - Services
- `%` - Parameters
- `#` - Tags
- `^` - Constants

Conventions
-----------

[](#conventions)

Syringe does not enforce naming or style conventions, with one exception. A service's name can be any you like, as long as it does not start with one of the reference characters, but a config alias is always seperated from a service name with a `.`, e.g. `myAlias.serviceName`. For this reason it can be useful to use `.` as a separator in your own service names, to "namespace" related services and parameters:

```
parameters:
    database.host: "..."
    database.username: "..."
    database.password: "..."

services:
    database.client:
        ...
```

Advanced Usage
==============

[](#advanced-usage)

The ContainerBuilder
--------------------

[](#the-containerbuilder)

The `ContainerBuilder` class is the main component of Syringe. It has several configuration options that allow you to customise the containers it builds.

### Base paths for config files

[](#base-paths-for-config-files)

In order to use configuration in a particular file, its filepath must be passed to the `ContainerBuilder`, which will use the loading system to convert a file into a PHP array. Syringe uses absolute paths when loading files, but this is obviously not ideal when you're passing config filepaths to the `ContainerBuilder`.

In order to get around this, the `ContainerBuilder` allows you to set a path or collection of paths to use as a base, so you can use relative filepaths when setting it up. For example, for a config file with absolute path of `/var/www/app/config/syringe.yml`, you could set a base path of `/var/www/app` and use `config/syringe.yml` as the relative filepath.

```
$basePath = "/var/www/app";
$resolver = new Lexide\Syringe\ReferenceResolver();

$builder = new Lexide\Syringe\ContainerBuilder($resolver, [$basePath]);
$builder->addConfigfile("config/syringe.yml");
...
```

If you use several base paths, Syringe will look for a config file in each base path in turn, so the order is important.

```
$basePaths = [
    "my-dir/config",    // both these paths contain a file called "foo.yml"
    "my-dir/app"
];
$resolver = new Lexide\Syringe\ReferenceResolver();

$builder = new Lexide\Syringe\ContainerBuilder($resolver, $basePaths);
$builder->addConfigfile("foo.yml");     // will load my-dir/config/foo.yml, as that is the first base path in the list
```

### Application root directory

[](#application-root-directory)

If you have services that deal with files, it can be very useful to have the base directory of the application as a parameter in DI config, so you can be sure any relative paths you use are correct. The `ContainerBuilder` allows you to set the base directory and the parameter name at runtime:

```
$builder->setApplicationRootDirectory("my/application/directory", "myParameterName");
```

If no key is passed, the default parameter name is `app.dir`.

### Container class

[](#container-class)

Some projects that use Pimple, such a [Silex](http://silex.sensiolabs.org/), extend the `Container` class to add functionality to their API. Syringe can create custom containers in this way by allowing you to set the container class it instantiates:

```
$builder->setContainerClass(Silex\Application::class);
$app = $builder->createContainer(); // returns a new Silex Application
```

### Loaders

[](#loaders)

Syringe can support any data format that can be translated into a nested PHP array. Each config file is processed by the loader system, which is comprised of a series of `Loader` objects, each handling a single data format, that take a file's contents and decode it into an array of configuration.

By default the `ContainerBuilder` has no loaders, so you need to add at least one before a container can be built:

```
$builder->addLoader(new Lexide\Syringe\Loader\YamlLoader());
```

#### Custom loaders

[](#custom-loaders)

By default Syringe supports YAML and JSON data formats for the configurations files, but it is possible to use any format that can be translated into a nested PHP array. The translation is done by a `Loader`; a class which takes a filepath, reads the file and decodes the data.

To create a `Loader` for your chosen data format, the class needs to implement the `LoaderInterface` and state what its name is and what file extensions it supports. For example, a hypothetical XML `Loader` would look something like this:

```
use Lexide\Syringe\Loader\LoaderInterface;

class XmlLoader implements LoaderInterface
{
    public function getName()
    {
        return "XML Loader";
    }

    public function supports($file)
    {
        return pathinfo($file, PATHINFO_EXTENSION) == "xml";
    }

    public function loadFile($file)
    {
        // load and decode the file, returning the configuration array
    }
}
```

Once created, such a loader can be used by adding it to the `ContainerBuilder` in the normal way.

### Populating a Container

[](#populating-a-container)

In addition to creating a new container, the `ContainerBuilder` can also populate an existing container that has been created elsewhere, with the `populateContainer` method:

```
$container = new Pimple\Container();
$builder->populateContainer($contianer);
```

### Method reference

[](#method-reference)

The `ContainerBuilder` class has the following methods available:

#### Constructor

[](#constructor)

- `__construct(Lexide\Syringe\ReferenceResolver $resolver, array $configPaths = [])`

    Constructs a new `ContainerBuilder` instance, with each $configPath set using the `addConfigPath` method

#### Container

[](#container)

- `createContainer()`

    Create a brand new container populated with all services defined in the configuration files that have been loaded into the `ContainerBuilder`
- `populateContainer(Pimple\Container $container)`

    Populate an existing container with services as per `createContainer`
- `setContainerClass($className)`

    Sets the class which will be instantiated when using `createContainer`

#### Config Files

[](#config-files)

- `addConfigFile($file, $alias = "")`

    Adds a new file path to load configuration from, optionally with an alias to prefix its keys with
- `addConfigFiles(array $files)`

    Adds several config files in one go. Elements with numeric keys are added without an alias, otherwise the key is used as the alias for that file:

```
  $files = [
      "file1.yml",
      "alias_two" => "file2.yml",
      "file3.yml",
      "alias_four" => "file4.yml"
  ]
```

- `addConfigPath($path)`

    Register a path to use as a base for relative config filepaths

#### Loaders

[](#loaders-1)

- `addLoader(Lexide\Syringe\Loader\LoaderInterface $loader)`

    Registers a loader to add support for a specific data format
- `removeLoader($name)`

    Remove a loader based on its name
- `removeLoaderByFile($file)`

    Remove any loader that supports this file

#### Misc

[](#misc)

- `setApplicationRootDirectory($path, $key = "")`

    Sets the directory to use as the root for this application, useful when processing relative file paths. The parameter name will be the $key, or `app.dir` if $key is empty

Credits
=======

[](#credits)

Written by Danny Smart ().

###  Health Score

38

—

LowBetter than 85% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity27

Limited adoption so far

Community20

Small or concentrated contributor base

Maturity72

Established project with proven stability

 Bus Factor1

Top contributor holds 66% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~52 days

Recently: every ~301 days

Total

50

Last Release

1657d ago

Major Versions

0.4.1 → 1.0.02015-11-05

1.4.2 → 2.0.02018-02-19

2.2.5 → v3.x-dev2021-11-03

PHP version history (4 changes)0.1.7PHP &gt;=5.3.0

1.3.2PHP &gt;=5.4.0

2.2.5PHP &gt;=5.6

v3.x-devPHP &gt;=7.3

### Community

Maintainers

![](https://www.gravatar.com/avatar/a01f73f5eea8a755e31d879b50f5862ee8a20e8d73daba1c15cb7e75e68796db?d=identicon)[downsider](/maintainers/downsider)

---

Top Contributors

[![downsider](https://avatars.githubusercontent.com/u/4508388?v=4)](https://github.com/downsider "downsider (95 commits)")[![Danny-Smart](https://avatars.githubusercontent.com/u/113538899?v=4)](https://github.com/Danny-Smart "Danny-Smart (21 commits)")[![dochne](https://avatars.githubusercontent.com/u/1678803?v=4)](https://github.com/dochne "dochne (13 commits)")[![exetrix](https://avatars.githubusercontent.com/u/38374120?v=4)](https://github.com/exetrix "exetrix (7 commits)")[![oliveremberton](https://avatars.githubusercontent.com/u/4114396?v=4)](https://github.com/oliveremberton "oliveremberton (3 commits)")[![B3none](https://avatars.githubusercontent.com/u/24966460?v=4)](https://github.com/B3none "B3none (3 commits)")[![leepercox](https://avatars.githubusercontent.com/u/6492146?v=4)](https://github.com/leepercox "leepercox (1 commits)")[![andywaite](https://avatars.githubusercontent.com/u/6773151?v=4)](https://github.com/andywaite "andywaite (1 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/lexide-syringe/health.svg)

```
[![Health](https://phpackages.com/badges/lexide-syringe/health.svg)](https://phpackages.com/packages/lexide-syringe)
```

###  Alternatives

[getkirby/cms

The Kirby core

1.5k535.5k352](/packages/getkirby-cms)[neos/flow

Flow Application Framework

862.0M451](/packages/neos-flow)[roadiz/roadiz

Roadiz is a modern CMS based on a polymorphic content-schema system which can handle many types of services. It’s based on Symfony component and Doctrine ORM for maximum performances and security.

3769.3k6](/packages/roadiz-roadiz)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
