PHP Inversion of Control
IoC framework for PHP, (*1)
, (*2)
Using an Inversion Of Control container you can define the business
logic of an application without depending on the specific framework. All
the core logic can be placed in simple PHP classes, where dependency are
injected by the container., (*3)
Installation
The library can be installed using Composer:, (*4)
# Install Composer
curl -sS https://getcomposer.org/installer | php
# Add php-ioc as a dependency (use dev-master until a stable release is out)
php composer.phar require laborra/php-ioc:dev-master
Basic Usage
The main library class is AppContext, that can be built using the ContextFactory helper,, (*5)
$config = [
// Bean configuration as PHP Array
//...
];
$context = ContextFactory::buildFromPHPArray($config);
// Or
$context = ContextFactory::buildFromFile('path/to/configurationfile.php');
Below is an example of context configuration with a bas, (*6)
// config.php
return [
'beans' => [
'beanOne' => [
'ClassOne',
'properties' => [
'valueProp' => 42,
],
],
'beanTwo' => [
'ClassTwo',
'properties' => [
'refOne' => '@beanOne',
],
],
'beanThree' => [
'ClassThree',
'constructorArgs' => [
@beanTwo,
'Answer to life the universe and everything'
],
],
],
]
class ClassOne
{
public $valueProp;
}
class ClassTwo
{
/** @var ClassOne */
public $refOne;
}
class ClassThree
{
/** @var ClassTwo */
private $refTwo;
/** @var string */
private $strProp
public function __constructor (ClassTwo $refTwo, $strAtg)
{
$this->strProp = $strArg;
}
public function getIt ()
{
return $this->strProp.' = '.$this->refTwo->refOne->valueProp;
}
}
// In application logic
$beanObj = $context->getBean('beanThree');
echo $beanObj->getIt(); // Answer to life the universe and everything = 42
Features
The current supported features are:
- Bean definition as request singleton scope
- Definition of relationships between beans
- Constructor arguments
- Class calls after bean creation
- Definition of context parameters
- Configuration based on PHP array, ConfigurationBuilder helper and YAML files, (*7)
Features available in future releases:
- Prototype scope for beans
- Support for Aspect Oriented Programming
- Cache for configuration and application context
- Support for multiple configuration files, (*8)
Defining Application Modules
Using an IoC container it is possible to build modularized applications.
Each module consists of a set of library classes, a set of dependency
and list of bean that must be implemented by the module client.
In this way, you can define an entire unit of business logic without
referencing any framework or specific environment., (*9)
Example of user management module
class UserService
{
/** @var IUserDAO
public $userDAO;
public function authenticate ($username, $password)
{
// Business logic to authenticate the user
$user = $this->userDAO->getByUserName($username);
if ($user == null) {
throw new Exception("User $username not found");
}
if ($user->password != $password) {
throw new Exception("Invalid credentials");
}
return $user;
}
public function register ($username, $password)
{
if ($username == "") {
throw new UserException("Username field cannot be blank");
}
if ($password == "") {
throw new UserException("Password field cannot be blank");
}
$user = $this->userDAO->create($username, $password);
return $user;
}
}
interface IUserDAO
{
function getByUsername ($username);
function create ($username, $password);
}
class User
{
public $username;
public $password;
}
beans:
userService:
class: UserService
properties:
userDAO: @userDAO, (*10)
When using the module in a complete application, we have to implement
the IUserDAO interface and declare it as a context bean., (*11)
class SpecificUserDAO implements IUserDAO
{
function getByUsername ($username)
{
// Query the database, possible using framework specific helpers
// ...
}, (*12)
function create ()
{
// ...
}
}, (*13)
beans:
userDAO:
class: SpecificUserDAO, (*14)
ConfigurationBuilder utility
In order to produce readable and maintenable configuration files, you
can use the ConfigurationBuilder class.
Below there is an example of a configuration built using this class., (*15)
$c = new ConfigurationBuilder();
$c->bean('beanOne', '\vendorName\library\ClassName')
->property('valueProp', 12)
->property('refProp', '@beanTwo')
->constructorArg('String value')
->constructorArg(42);
return $c->build();
You can extend the configuration builder class to add your own custom
methods. Doing so, you can create shortcut to some very often used
configuration parts., (*16)
class SpecificConfigurationBuilder extends ConfigurationBuilder
{
public function beanOneRef()
{
return $this->prop('refProp', '@beanOneId');
}
}