In many frameworks, developer has to deal with usually huge structured data to represent the application and application components configuration. This approach has several major drawbacks: it leads to very hard to read and maintain files, and mostly, it needs the developer to know by heart all configuration directives and options.
For Objective PHP, we tried hard to find another way to handle configuration directives, a way that would address those problems.
After several experiments, we came up with an objective approach: all configuration directives are exposed as objects, and
configuration files only contain one-level arrays filled with instances of ObjectivePHP\Config\DirectiveInterface
.
Objective PHP exposes this interface, but also several abstract classes to ease Directives conception. There a three kind of
directives at this time: SingleValueDirective
, StackedValueDirective
and SingleValueDirectiveGroup
. Their behavior is
described later in this chapter.
All directives of a project configuration are imported in an ObjectivePHP\Confi\Config
instance, available by default through
Application::getConfig()
, making it available almost everywhere in the application.
The Config object extends ObjectivePHP\Primitives\Collection\Collection
, and as such offers lots of high-level manipulation
methods on the configuration data. This object can import DirectiveInterface
instances through either Config::import()
(one by one)
or Config::fromArray()
(an array of directives at once).
Once imported, the DirectiveInterface object is not kept as is. It is used by the Config object to create or merge entries in the configuration data.
The configuration directive value can then be fetched using the Config::get($key, $default = null)
method, as one would do on
any Collection
.
Note
Directive key (or prefix when working with group) are equals to the classes name, so that it is not needed to remember keys, and prevent from making typos when referring a given directive in the Config object.
A SingleValueDirective can contain only one value, which can be scalar or structured (object, array). In case the same Directive is imported twice or more, the latest imported overwrites the previous one by default:
class Single extends ObjectivePHP\Config\SingleValueDirective
{
// default mechanism inherited from abstract is enough
}
$config->import(new Single('x'))
->import(new Single('y'));
$config->get(Single::class) == "y";
This behaviour can be altered by changing the DirectiveMerge policy:
$config->import(new Single('x'))
->setMergePolicy(MergePolicy::COMBINE)
->import(new Single('y'));
$config->get(Single::class) == ["x", "y"];
A StackedValueDirective is pretty close to the SingleValue used with the COMBINE merge policy, but with a major difference: its value is always an array, even if only one directive of that kind is imported into the Config object:
class Stacked extends ObjectivePHP\Config\StackedValueDirective
{
// default mechanism inherited from abstract is enough
}
$config->import(new Stacked('x'));
$config->get(Stacked::class) == ["x"];
$config->import(new Stacked('y'));
$config->get(Stacked::class) == ["x", "y"];
With this directive type, values will be handled just like with Single Value, especially the merge policy, but with a main difference: each single entry in a Single Value Group has an individual identifier, that will be concatenated to the group prefix:
class Grouped extends ObjectivePHP\Config\SingleValueDirectiveGroup
{
}
$config->import(new Grouped('first', 'first value');
$config->import(new Grouped('second', 'second value');
$config->get(Grouped::class . '.first') == 'first value';
// all grouped directives can be fetched as new Config object using subset()
$config->subset(Grouped::class)->toArray() == ['first' => 'first value', 'second' => 'second value'];
Note
While fetching syntax might not be as intuitive as one could expect, remember that the idea behind all this is that application developers should only deal with directives instantiation, since configuration directives are exepexted to be used by the framework itself and components. All other, arbitrary, application (especially business) parameters should be handled using Application::setParam() and Application::getParam(), not Config.
Objective PHP and its packages comes with a few directives:
Class | Type | Description |
---|---|---|
ActionNamespace | Stack | Namespace prefixes where to search for action classes |
ApplicationName | Single | Application name |
LayoutsLocations | Stack | Paths where to search for layout scripts |
Route | Group | Simple Router route definitions |
ViewsLocations | Stack | Paths where to search for view scripts (optional) |
Class | Type | Description |
---|---|---|
Service | Group | Service specification |
Class | Type | Description |
---|---|---|
EloquentCapsule | Group | Eloquent ORM Capsule DB connection configuration |
Class | Type | Description |
---|---|---|
EntityManager | Group | Doctrine Entity manager and DB connection |