Same as JavaScript, STDOUT MVC API and Console MVC API allow developers to bind logic to application lifecycle events (addEventListener) in request-response handling process. Syntax:
$object->addEventListener(EVENT_TYPE, CLASS_NAME);
Following EVENT_TYPE are available for STDOUT MVC API, corresponding to a prototype respective listener must extend, triggered on a lifecycle event:
Event Type | Class Prototype | Triggered |
Lucinda\STDOUT\EventType::START | Lucinda\STDOUT\EventListeners\Start | Before stdout.xml is read |
Lucinda\STDOUT\EventType::APPLICATION | Lucinda\STDOUT\EventListeners\Application | After stdout.xml is read, before request is read |
Lucinda\STDOUT\EventType::REQUEST | Lucinda\STDOUT\EventListeners\Request | After request is read, before controller runs |
Lucinda\STDOUT\EventType::RESPONSE | Lucinda\STDOUT\EventListeners\Response | After view resolver runs, before response is outputted |
Lucinda\STDOUT\EventType::END | Lucinda\STDOUT\EventListeners\End | After response is outputted |
Similar EVENT_TYPE are available for Console MVC API, corresponding to a prototype respective listener must extend, triggered on a lifecycle event:
Event Type | Class Prototype | Triggered |
Lucinda\ConsoleSTDOUT\EventType::START | Lucinda\ConsoleSTDOUT\EventListeners\Start | Before stdout.xml is read |
Lucinda\ConsoleSTDOUT\EventType::APPLICATION | Lucinda\ConsoleSTDOUT\EventListeners\Application | After stdout.xml is read, before request is read |
Lucinda\ConsoleSTDOUT\EventType::REQUEST | Lucinda\ConsoleSTDOUT\EventListeners\Request | After request is read, before controller runs |
Lucinda\ConsoleSTDOUT\EventType::RESPONSE | Lucinda\ConsoleSTDOUT\EventListeners\Response | After view resolver runs, before response is outputted |
Lucinda\ConsoleSTDOUT\EventType::END | Lucinda\ConsoleSTDOUT\EventListeners\End | After response is outputted |
Framework comes with its own bindings, necessary to integrate APIs it's composed of, but developers will more often than not need to add their own, as long as rules are followed:
Please keep in mind event listeners will be executed in the order they are set!
Abstract class Lucinda\STDOUT\EventListeners\Start / Lucinda\ConsoleSTDOUT\EventListeners\Start listens to events that execute BEFORE stdout.xml is read.
A common example is the need to set start time, in order to benchmark duration of handling later on:
namespace Lucinda\Project\EventListeners;
class StartListener extends Lucinda\STDOUT\EventListeners\Start
{
public function run()
{
$this->attributes->setStartTime(microtime(true));
}
}
Save class above in src/EventListeners then add this line to index.php right after Lucinda\STDOUT\FrontController is instanced:
$object->addEventListener(Lucinda\STDOUT\EventType::START, Lucinda\STDOUT\EventListeners\StartListener::class);
Since method setStartTime does't exist in in Lucinda\Project\Attributes, you need to modify it and add these lines:
private $startTime;
public function setStartTime(float $startTime): void
{
$this->startTime = $startTime;
}
public function getStartTime(): float
{
return $this->startTime;
}
Abstract class Lucinda\STDOUT\EventListeners\Application / Lucinda\ConsoleSTDOUT\EventListeners\Application listens to events that execute AFTER stdout.xml is read.
A common example is to integrate new features via stdout.xml (eg: a Rest API to call later):
<rest_api host="api.example.com" authkey="asdfgh"/>
Which needs following listener:
namespace Lucinda\Project\EventListeners;
use Lucinda\Project\Models\RestAPI;
class RestAPIListener extends Lucinda\STDOUT\EventListeners\Application
{
public function run()
{
$tag = $this->application->getTag("rest_api");
$restAPI = new RestAPI((string) $tag->host, (string) $tag->authKey);
$this->attributes->setRestAPI($restAPI);
}
}
Save class above in src/EventListeners then add this line to index.php in the right place after Lucinda\STDOUT\FrontController is instanced:
$object->addEventListener(Lucinda\STDOUT\EventType::APPLICATION, Lucinda\STDOUT\EventListeners\RestAPIListener::class);
Since method setRestAPI does't exist in Lucinda\Project\Attributes, you need to modify it and add these lines:
private $restAPI;
public function setRestAPI(Lucinda\Project\Models\RestAPI $restAPI): void
{
$this->restAPI = $restAPI;
}
public function getRestAPI(): Lucinda\Project\Models\RestAPI
{
return $this->restAPI;
}
Abstract class Lucinda\STDOUT\EventListeners\Request / Lucinda\ConsoleSTDOUT\EventListeners\Request listens to events that execute AFTER http request / console request is processed.
A common example is user country detection:
namespace Lucinda\Project\EventListeners;
use Lucinda\Project\Models\CountryDetector;
class CountryDetectionListener extends Lucinda\STDOUT\EventListeners\Request
{
public function run()
{
$countryDetector = new CountryDetector($this->request->getClient()->getIP(), $this->request->headers());
$this->attributes->setCountry($countryDetector->getCountry());
}
}
Save class above in src/EventListeners then add this line to index.php in the right place after Lucinda\STDOUT\FrontController is instanced:
$object->addEventListener(Lucinda\STDOUT\EventType::REQUEST, Lucinda\STDOUT\EventListeners\CountryDetectionListener::class);
Since method setCountry does't exist in in Lucinda\Project\Attributes, you need to modify it and add these lines:
private $country;
public function setCountry(Lucinda\Project\Models\Country $restAPI): void
{
$this->country = $country;
}
public function getCountry(): Lucinda\Project\Models\Country
{
return $this->country;
}
Abstract class Lucinda\STDOUT\EventListeners\Response / Lucinda\ConsoleSTDOUT\EventListeners\Response listens to events that execute AFTER Lucinda\MVC\Response body was set but BEFORE it's rendered back to caller.
A common example comes from a need of crypting response on top of SSL:
namespace Lucinda\Project\EventListeners;
use Lucinda\Project\Models\Encryptor;
class EncryptionListener extends Lucinda\STDOUT\EventListeners\Response
{
public function run()
{
$encryptor = new Encryptor();
$this->response->setBody($encryptor->encrypt($this->response->getBody()));
}
}
This way, whoever knows the URL of a web service will see garbled response unless he has a key to decrypt it. So save class above in src/EventListeners then add this line to index.php in the somewhere right before $object->run();:
$object->addEventListener(Lucinda\STDOUT\EventType::RESPONSE, Lucinda\STDOUT\EventListeners\EncryptionListener::class);
Abstract class Lucinda\STDOUT\EventListeners\End / Lucinda\ConsoleSTDOUT\EventListeners\End listens to events that execute AFTER Lucinda\MVC\Response was rendered back to caller.
A common example is the need to set end time, in order to benchmark duration of handling:
namespace Lucinda\Project\EventListeners;
class EndListener extends Lucinda\STDOUT\EventListeners\End
{
public function run()
{
$duration = microtime(true)-$this->attributes->getStartTime();
$this->attributes->getLogger()->info("Duration: ".$duration);
}
}
Save class above in src/EventListeners then add this line to index.php right before $object->run();:
$object->addEventListener(Lucinda\STDOUT\EventType::END, Lucinda\STDOUT\EventListeners\EndListener::class);