Services¶
This framework’s main services are:
- Event Manager (
\Ascmvc\Mvc\AscmvcEventManager
), - Service Manager (
\Pimple\Container
).
Event Manager¶
The \Ascmvc\Mvc\AscmvcEventManager
event manager is an extension of the \Zend\EventManager\EventManager
.
It is available through the application object’s getEventManager()
method. It is configured WITH a
\Zend\EventManager\SharedEventManager
. It is possible to get the shared manager by calling the main
event manager’s getSharedManager()
method. This same shared manager will also be readily available
within each controller aggregate by getting it from the controller’s PSR-14 event dispatcher (event bus)
like so:
// From within a controller's action method for example.
$sharedEventManager = $this->eventDispatcher->getSharedManager();
By doing so, it becomes possible to dispatch custom events not only to other parts of the current aggregate, but to also dispatch custom events to other aggregates outside of the current controller aggregate. Thus, Aspect-Oriented Programming becomes a clear possibility and allows for separation of concerns and code modularity.
Note
Each controller has access to a segregated event dispatcher (event bus), as the controller is considered to be the Root Aggregate of its Event Sourcing aggregate.
For more information on configuring the controller’s event dispatcher, please see the Event Sourcing Configuration section.
The main AscmvcEventManager
is designed to be able to trigger \Ascmvc\Mvc\AscmvcEvent
events for the
entire application. The \Ascmvc\Mvc\AscmvcEvent
class is an extension of the Zend\EventManager\Event
class. Here is a list of the framework’s main MVC events:
/**#@+
* Mvc events triggered by the Event Manager
*/
const EVENT_BOOTSTRAP = 'bootstrap';
const EVENT_ROUTE = 'route';
const EVENT_DISPATCH = 'dispatch';
const EVENT_RENDER = 'render';
const EVENT_FINISH = 'finish';
/**#@-*/
These events correspond to listener interfaces that are implemented by default in every controller. Thus,
from within any controller, it is possible to tap into a specific MVC event, or to downright interrupt
the application’s flow by returning a \Zend\Diactoros\Response
, from within these listener methods.
Here is a short description of each main event:
- EVENT_BOOTSTRAP (onBootstrap): this event is triggered right after the booting and initialization phases of the application. Using the onBootstrap method within a controller class makes it possible to run code immediately after the middleware pipeline. And, if you attach a listener to this event with a high priority, you can run code before the execution of any middleware, any controller or any service.
- EVENT_ROUTE (onRoute): this event is triggered after bootstrapping is done and the router class has been instantiated, but before the router actually tries to resolve the request URI to a handler.
- EVENT_DISPATCH (onDispatch): this event is triggered after the router has instantiated a controller manager with a requested handler, but before the controller manager actually hands control over to the requested controller.
- EVENT_RENDER (onRender): this event is triggered once the controller has returned its output, but before the output is parsed by the template managers.
- EVENT_FINISH (onFinish): this event is triggered once rendering is done and/or a response object is available (event short-circuit). This event allows to manipulate the response object before returning the response to the client.
Note
You should avoid as much as possible to use the onBootstrap() method within the controller classes, as this would not scale very well if there is a large number of controllers.
Note
If you run the framework using Swoole, you should avoid using a high priority AscmvcEvent::EVENT_FINISH
listeners to manipulate the response, because this event will be ignored by Swoole. To achieve the same result, one should use a very low priority listener on the AscmvcEvent::EVENT_RENDER
event instead.
Here is an example of a controller that is tapping into the AscmvcEvent::EVENT_BOOTSTRAP
event in order to short-circuit the
application’s execution and return an early response:
<?php
namespace Application\Controllers;
use Ascmvc\Mvc\AscmvcEvent;
use Ascmvc\Mvc\Controller;
use Zend\Diactoros\Response;
class FakeController extends Controller
{
public static function onBootstrap(AscmvcEvent $event)
{
$response = new Response();
$response->getBody()->write('Hello World!');
return $response;
}
// [...]
In order to attach a new listener to one of the main MVC events, you can simply do it this way:
$this->eventManager->attach(AscmvcEvent::EVENT_BOOTSTRAP, function ($event) use ($serviceManager) {
// do something here
}, 3);
Note
The last parameter is a priority indicator. The higher the indicator, the higher the priority of the listener. Any listener can be given a priority of three (3) or more in order to run BEFORE any of the preconfigured listeners.
To learn more about the LightMVC events and and corresponding listeners, please see the LightMVC Framework’s API documentation.
For more information on available methods of the \Zend\EventManager\EventManager
, please see
the ZF documentation,
and the ZF API documentation.
Service Manager¶
The LightMVC Service Manager is an instance of the \Pimple\Container
class. It is a simple implementation
of a Registry and allows for easy storage and retrieval of objects and data. The Pimple container object
implements the \ArrayAccess
interface and thus, can be accessed as if it was an array.
Storing a service is as easy as this:
// Store SomeService instance
$serviceManager['someService'] = function ($serviceManager) {
return new SomeService();
};
And, retrieving the same service is just as easy as this:
// Retrieve SomeService instance
$someService = $serviceManager['someService'];
It is possible to store a service within the container as a lazy-loading one. To do so, you must use the
container’s factory()
method:
// Store SomeService instance
$serviceManager['someService'] = $serviceManager->factory(function ($serviceManager) {
// Retrieve the database connection and inject it within the SomeService constructor
return new SomeService($serviceManager['em1]);
});
To learn more about Pimple, please visit the Pimple Website.