webspot / messagebus
Webspot MessageBus
Requires
- php: >=5.4.0
- webspot/api: >=0.9.5,<2.0.0
Requires (Dev)
- codeclimate/php-test-reporter: dev-master
This package is not auto-updated.
Last update: 2015-12-07 13:06:50 UTC
README
Inspired by MessageRequest-Oriented Middleware, though not implementing its asynchronous nature.
The idea is to decouple application layers by not having their classes interact with each other directly. Instead they get a MessageBus which they ask to respond to a RequestMessage.
The RequestMessage
A RequestMessage is an immutable object describing what the client expects. This means that any request data must be
passed through the constructor. A RequestMessageInterface
implementation consists of the following methods:
- getName() : string returns a unique string identifying the request
- getRequestData() : array returns the requests data serialized into an array
Other getters may be defined upon the RequestMessage to allow working with non-array-serialized data. Any method changing the message must return a new instance with the change instead of changing the object.
The ResponseMessage
A ResponseMessage is an immutable object describing the server's response to a request. This means that any response
data must be passed through the constructor. A ResponseMessageInterface
implementation consists of the following
methods:
- getRequestName() : string returns a unique string identifying the request
- getResponseData() : array returns the response data serialized into an array
Other getters may be defined upon the ResponseMessage to allow working with non-array-serialized data. Any method changing the message must return a new instance with the change instead of changing the object.
The MessageBus
The MessageBus consists of a Protocol object and an implementation of the
MessageBusInterface::handle(RequestMessageInterface $message) : void
method. The handle()
method will throw an
UnhandledMessageException
the MessageRequest didn't generate a Response.
An example
Let's say we're in a Controller and want to fetch an Entity. This might look like this:
<?php namespace Application\Controller; use Webspot\MessageBus\MessageRequest; use Webspot\MessageBus\MessageBusInterface; class PostsController { /** @var MessageBusInterface */ private $messageBus; public function __construct(MessageBusInterface $messageBus) { $this->messageBus = $messageBus; } public function getAction($id) { // Assume we have an extension of the RequestMessageInterface which adds a getEntity() method $message = new FindEntityMessage('posts.find', $id); $response = $this->serviceBus->handle($message); return new JsonResponse($response->getResponseData()); } public function getCommentsAction($postId) { // Assume we have an extension of the RequestMessageInterface which adds a getEntities() method $message = new GetEntitiesMessage('posts.comments.get', $postId); $response = $this->serviceBus->handle($message); return new JsonResponse($message->getCommentCollection()->toArray()); } }
The Model layer would define HandlerProviders extending the Webspot\MessageBus\HandlerProviderInterface
. For the
above use-case a PostsHandlerProvider
would provide Handlers extending the Webspot\MessageBus\HandlerInterface
accepting the posts.find
and posts.comments.get
request messages.
As such the Model layer's MessageBus construction would look somewhat like the following:
<?php use Symfony\Component\EventDispatcher\EventDispatcher; use Webspot\EventManager\EventManager; use Webspot\MessageBus\MessageBus; use Webspot\MessageBus\Protocol; $messageBus = new MessageBus(); $postsHandlerProvider = new PostsHandlerProvider($postsRepository); $messageBus->register($postsHandlerProvider);
We could even take it a step further and even push the HttpResponse generation through another MessageBus:
<?php namespace Application\Controller; use Webspot\MessageBus\MessageBusInterface; class PostsController { /** @var MessageBusInterface */ private $serviceBus; /** @var MessageBusInterface */ private $viewBus; public function __construct(MessageBusInterface $serviceBus, MessageBusInterface $viewBus) { $this->serviceBus = $serviceBus; $this->viewBus = $viewBus; } public function getAction($id) { // Assume we receive an extension of the ResponseMessageInterface which adds a getEntity() method $serviceRequest = new FindEntityMessage('posts.find', $id); $serviceResponse = $this->serviceBus->handle($serviceRequest); // Assume we receive an extension of the ResponseMessageInterface which adds a getHttpResponse() method $viewRequest = new PrepareResponseMessage('posts.view.json', $serviceResponse->getEntity()); $viewResponse = $this->viewBus->handle($viewRequest); return $viewResponse->getResponse(); } }
Where the ViewBus would for example have a service using a Fractal\Transformer
to transform a Post Entity into an
array and wrap it into a HttpFoundation JsonResponse object.