PHPackages                             mindplay/stockpile - 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. mindplay/stockpile

Abandoned → [mindplay/unbox](/?search=mindplay%2Funbox)ArchivedLibrary

mindplay/stockpile
==================

Strongly-typed, stand-alone configuration/service-container for PHP

3.2.1(10y ago)5110LGPL-3.0+PHPPHP &gt;=5.3.0

Since May 2Pushed 10y ago1 watchersCompare

[ Source](https://github.com/mindplay-dk/stockpile)[ Packagist](https://packagist.org/packages/mindplay/stockpile)[ RSS](/packages/mindplay-stockpile/feed)WikiDiscussions master Synced 2mo ago

READMEChangelogDependencies (3)Versions (18)Used By (0)

stockpile
=========

[](#stockpile)

[![Build Status](https://camo.githubusercontent.com/b353f8f65968a38a44ba8ecb6b0e26f86fe38e7aa488eb7bce4cc2b53726ea99/68747470733a2f2f7472617669732d63692e6f72672f6d696e64706c61792d646b2f73746f636b70696c652e706e67)](https://travis-ci.org/mindplay-dk/stockpile)

[![Code Coverage](https://camo.githubusercontent.com/75a5aa22cb751dd514e1279122e297ba780675d7abf5135ed0920534d174607f/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6d696e64706c61792d646b2f73746f636b70696c652f6261646765732f636f7665726167652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/mindplay-dk/stockpile/?branch=master)

Stockpile provides a base-class for easy implementation of the [service locator](http://en.wikipedia.org/wiki/Service_locator_pattern)pattern, and provides simple means for implementing simple, efficient [dependency injection](http://en.wikipedia.org/wiki/Dependency_injection).

⚠️ **Service Locator is generally considered to be an anti-pattern** - if you're looking for a modern DI container that does not encourage or optimize for that pattern, but still provides great IDE support, please check out [Unbox](https://github.com/mindplay-dk/unbox).

Tested and designed for PHP 5.3 and up.

See "example.php" in the root-folder for an example of how to use this class.

### Overview

[](#overview)

The `Container` base class will parse `@property` annotations on your class - these provide design-time IDE support, while the type-hints and property-names in your class-level doc-block are also picked up and parsed by the base-class, which is then able to provide run-time type-checking and extra safety.

### API Overview

[](#api-overview)

The life-cycle of a `Container` class has two stages: it is initially open for registration and configuration, and then gets sealed (using the `seal()` method) prevent any further modifications. In other words, it is initially write-only, and then becomes read-only.

Configuration methods, available prior to calling `seal()`:

```
register(string $name, Closure $init)   # register component creation function
unregister(string $name)                # unregister a component
configure(Closure|Closure[] $config)    # configure a registered component
shutdown(Closure $function)             # dispose of components after use
load(string $path)                      # load an external configuration file

```

Other methods, available at all times:

```
getRootPath()                           # get configuration files root path
invoke(callable $function, $params)     # invoke a function with components as arguments
isActive(string $name)                  # check if a component has been initialized
isDefined(string $name)                 # check if a component has been defined
isRegistered(string $name)              # check if a component has been registered

```

A "defined" component, is a property of your container that has been defined with an `@property` annotation. A "registered" component has been registered using the `register()` method, or has been initialized directly by setting the property. An "active" component has been initialized, e.g. by accessing the property after the container has been sealed.

### Usage

[](#usage)

By using this class as the base-class for the global point of entry for your application or module, your container will receive proper IDE-support and run-time type-checking e.g. for service interfaces and configuration values.

A basic container class migth look like this:

```
use mindplay\stockpile\Container;

/**
 * @property string $db_username
 * @property string $db_password
 *
 * @property-read PDO $db application-wide database connection
 */
class MyApp extends Container
{
    ...
}
```

Usage of the class might be something like this:

```
$container = new MyApp(__DIR__ . '/config');

$container->load('default.php'); // load and execute "config/default.php"
```

Note that there is deliberately no support for configuration via nested arrays, XML/JSON/YAML data files, or any other schema-less means of configuration - these add complexity, they provide no support for design-time inspections in a modern IDE, they are unnecessary and provide no clear benefits.

#### Configuration Files

[](#configuration-files)

Your `config/default.php` being loaded in the example s simply a PHP script, which might look something like this:

```
/** @var MyApp $this */

$this->db_username = 'foo';
$this->db_password = 'bar';
```

Notice the `@var` type-hint, which provides design-time IDE support.

Once the container has been sealed, when the `$db` property is accessed for the first time, the registered creation function will be called. Arguments to this function correspond to property-names - you should type-hint these for IDE support, when possible; in this example both properties are strings.

#### Dependency Resolution

[](#dependency-resolution)

Asking for required components (via arguments to closures), enables the container to initialize dependencies (other components) in cascade. For example, let's say that several different components depend upon a cache component - here's an example of registering a view engine with a dependency a cache component:

```
$container->register(
    'view',
    function (FileCache $cache) {
        // cache argument injected via $container->cache

        return new ViewEngine($cache, ...);
    }
);
```

#### Layered Configuration

[](#layered-configuration)

When configuration happens in layers (e.g. multiple configuration-files for different environments) you can further configure a named component, by using additional anonymous functions, with type-hints for IDE-support.

For example, to send a `set names utf8` query to MySQL when the `$db` component gets initialized, you might add this:

```
$container->configure(
    function (PDO $db) {
        $db->exec("set names utf8");
    }
);
```

#### Sealing

[](#sealing)

Once you're all done configuring your container, before you can start using the components, you need to seal it - this prevents any further attempts to make changes accidentally, and also verifies that the configuration of every defined component is complete.

```
$container->db_username = '...';
$container->db_password = '...';

$container->seal(); // prevent further changes (exception if incomplete)
```

Note that, if you have components that are deliberately absent, you must explicitly set these to null - this forces you to actively make decisions and leads to more self-documenting code.

#### Eager vs Lazy

[](#eager-vs-lazy)

You won't find an option to toggle eager/lazy loading of components - it is assumed you want everything to initialize as late as possible. If you do have a component that is available immediately, simply inject that component directly - for example:

```
$container->logger = new Logger(...); // eager construction, vs lazy register()
```

### Caching

[](#caching)

Very large applications (with many containers and lots of properties) may benefit from caching - the included benchmark demonstrates the benefit of this, showing a performance increase of ~ 3.5x, but don't overestimate the impact of this difference; for most applications, the difference in practice may be at the most a couple of milliseconds, since it's already pretty fast without caching.

To configure caching, you need to override the protected `getCache()` method - you might for example use a subfolder under a Container's root path:

```
class MyContainer extends Container
{
    /**
     * @return CacheProvider
     */
    protected function getCache()
    {
        return new FileCache($this->getRootPath() . '/cache');
    }
}
```

Note that this folder must be writable by the web server's user account.

### Advanced Use

[](#advanced-use)

For advanced uses, such as building a Container with specialized behavior (e.g. defining components by other means besides parsing `@property` annotations) an abstract base class `AbstractContainer` is available, with a bunch more protected API methods available. Explore on your own, if needed.

###  Health Score

30

—

LowBetter than 64% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity14

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity67

Established project with proven stability

 Bus Factor1

Top contributor holds 100% 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 ~48 days

Recently: every ~5 days

Total

17

Last Release

3983d ago

Major Versions

1.1.1 → 2.0.02014-01-28

2.4.1 → 3.0.02014-11-16

### Community

Maintainers

![](https://www.gravatar.com/avatar/9445f567f43ee7a963270651e40e533634586f959e4df3d5398d001b1cb49be8?d=identicon)[mindplay.dk](/maintainers/mindplay.dk)

---

Top Contributors

[![mindplay-dk](https://avatars.githubusercontent.com/u/103348?v=4)](https://github.com/mindplay-dk "mindplay-dk (56 commits)")

### Embed Badge

![Health badge](/badges/mindplay-stockpile/health.svg)

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

PHPackages © 2026

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