Skip to content

Instantly share code, notes, and snippets.

@mbrowne
Created October 22, 2017 11:50
Show Gist options
  • Save mbrowne/37d4c8e7dbda031ba3b86fcfde04f5d8 to your computer and use it in GitHub Desktop.
Save mbrowne/37d4c8e7dbda031ba3b86fcfde04f5d8 to your computer and use it in GitHub Desktop.
Sketch of role-player-wraps-role implementation in PHP.
/*
This is just a demo to show the concept. For a full implementation,
see https://github.com/mbrowne/dci-php
*/
trait RolePlayer
{
private $roles = [];
private $roleMethods = [];
function addRole($roleClassName) {
$role = new $roleClassName($this);
$this->roles[] = $role;
//Get method names for this role using reflection
...
foreach ($methodNames as $methodName) {
$this->roleMethods[$methodName][$roleClassName] = $role;
}
}
function removeAllRoles() {
$this->roles = [];
$this->roleMethods = [];
}
function __call($methodName, $args) {
$rolesWithThisMethod = $this->roleMethods[$methodName];
if (count($rolesWithThisMethod) == 1) {
$role = current($rolesWithThisMethod);
//Call $role->$methodName() with the given arguments
return call_user_func_array([$role, $methodName], $args);
}
//else handle naming conflict or role method not found
...
}
}
abstract class Role
{
private $data;
function __construct($data) {
$this->data = $data;
}
function __get($propName) {
return $this->data->$propName;
}
function __set($propName, $val) {
$this->data->$propName = $val;
}
function __call($methodName, $args) {
return call_user_func_array([$this->data, $methodName], $args);
}
}
class Account
{
use RolePlayer;
...
}
class TransferMoney extends Object
{
...
function __construct($sourceAcct, $destinationAcct, $amount) {
$this->sourceAcct = $sourceAcct;
$sourceAcct->addRole('TransferMoney\SourceAccount');
...
}
...
}
//PHP doesn't support inner classes so I'm using a namespace instead
namespace TransferMoney
{
class SourceAccount extends \Role {
...
}
...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment