domin ( domain model interface ) is an administration interface for abstract Domain Models using
the Command Object pattern., (*1)
For an example of how to use use, check out the sample application., (*2)
Model
Every ability of a system is represented by an [Action
] which specifies how to execute it and what [Parameters
]
it requires. Therefore domin can take care of getting missing parameters from the user using [Fields
]. Actions may
return values which are presented using [Renderers
]., (*3)
Installation
To use domin in your project, require it with Composer, (*4)
composer require rtens/domin
If you would like to develop on domin, download it with Composer and execute the specification with scrut, (*5)
composer create-project -sdev rtens/domin
cd domin
vendor/bin/scrut spec
Quick Start
To run domin as a web application with curir as delivery system, paste the following code into index.php
, (*6)
use rtens\domin\delivery\web\adapters\curir\root\IndexResource;
use rtens\domin\delivery\web\WebApplication;
use watoki\curir\WebDelivery;
WebDelivery::quickResponse(IndexResource::class,
WebDelivery::init(null,
WebApplication::init(function (WebApplication $app) {
// Set-up $app here (e.g. $app->actions->add('foo', ...))
})));
To run domin with silex, past this code into index.php
, (*7)
use rtens\domin\delivery\web\adapters\silex\SilexControllerProvider;
use rtens\domin\delivery\web\WebApplication;
use Silex\Application;
require_once __DIR__ . '/vendor/autoload.php';
$app = new Application();
$app->mount('/', new SilexControllerProvider(
WebApplication::init(function (WebApplication $app) {
// Set-up $app here (e.g. $app->actions->add('foo', ...))
})));
$app->run();
And then start a development server to access the application on localhost:8000, (*8)
$ php -S localhost:8000 index.php
To get the CLI application running, paste this code into cli.php
, (*9)
use rtens\domin\delivery\cli\CliApplication;
CliApplication::run(CliApplication::init(function (CliApplication $app) {
// Set-up $app here (e.g. $app->actions->add('foo', ...))
}));
and run it with, (*10)
$ php cli.php
Action!
[Actions
] decide what [Parameters
] they need, how to fill()
them with default values and, most importantly, how to execute()
them.
The way domin knows what actions there are is through the [ActionRegistry
], so all actions need to be added to it., (*11)
There are several ways to create actions:, (*12)
Implementing Action
The most straight-forward although probably not most convenient way is to create an implementation of Action
for
every ability of the system., (*13)
class MyAction implements Action {
public function caption() {
return 'Some Action';
}
public function description() {
return 'Some Description';
}
public function parameters() {
return [
new Parameter('foo', new StringType()),
new Parameter('bar', new ClassType(\DateTime::class))
];
}
public function fill(array $parameters) {
$parameters['foo'] = 'default value of foo';
return $parameters;
}
public function execute(array $parameters) {
return "Make it so! " . json_encode($parameters);
}
}
$actionRegistry->add('my', new MyAction());
Extending ObjectAction
If you represent abilities with DTOs, you can extend you actions from the ObjectAction
to infer Parameters
from
the properties of these classes using reflection. This sub-class can then be made generic for example by using
a Command Bus., (*14)
class MyAction extends ObjectAction {
public function __construct($class, TypeFactory $types, CommandBus $bus) {
parent::__construct($class, $types);
$this->bus = $bus;
}
protected function executeWith($object) {
$this->bus->handle($object);
}
}
$actionRegistry->add('my', new MyAction(MyCommand::class, $types, $bus));
$actionRegistry->add('your', new MyAction(YourCommand::class, $types, $bus));
$actionRegistry->add('their', new MyAction(TheirCommand::class, $types, $bus));
Generating ObjectActions
With a generic way to execute actions, you can use the ObjectActionGenerator
to generate and register actions from
all classes in a folder automatically., (*15)
(new ObjectActionGenerator($actionRegistry, $typeFactory))->fromFolder('model/commands', function ($object) {
$bus->handle($object);
});
Using MethodAction
If you don't feel like creating a class for every command, you can use the MethodAction
to infer parameters
from a method signature., (*16)
$actionRegistry->add('my', new MethodAction($handler, 'handleMyCommand', $typeFactory));
$actionRegistry->add('your', new MethodAction($handler, 'handleYourCommand', $typeFactory));
$actionRegistry->add('their', new MethodAction($handler, 'handleTheirCommand', $typeFactory));
Generating MethodActions
There is also a MethodActionGenerator
to register all methods of an object., (*17)
(new MethodActionGenerator($actionRegistry, $typeFactory))->fromObject($handler);
License
domin is released under the MIT License, (*18)