ResourcesΒΆ
In order to perist resources or retrieve resources to represent, PhlyRestfully
uses a PhlyRestfully\Resource instance. This class simply triggers an event
based on the operation requested; you, as a developer, provide and attach
listeners to those events to do the actual work.
PhlyRestfully\Resource defines the following events, with the following
event parameters:
| Event name | Parameters |
|---|---|
| create |
|
| update |
|
| replaceList |
|
| patch |
|
| delete |
|
| deleteList |
|
| fetch |
|
| fetchAll | |
Event listeners receive an instance of PhlyRestfully\ResourceEvent, which
also composes the route matches and query parameters from the request. You may
retrieve them from the event instance using the following methods:
getQueryParams()(returns aZend\Stdlib\Parametersinstance)getRouteMatch()(returns aZend\Mvc\Router\RouteMatchinstance)getQueryParam($name, $default = null)getRouteParam($name, $default = null)
Within your listeners, you have the option of throwing an exception in order to
raise an ApiProblem response. The following maps events to the special
exceptions you can raise; all exceptions are in the PhlyRestfully\Exception
namespace, except where globally qualified:
| Event name | Parameters |
|---|---|
| create | CreationException |
| update | UpdateException |
| replaceList | UpdateException |
| patch | PatchException |
| delete | \Exception |
| deleteList | \Exception |
| fetch | \Exception |
| fetchAll | \Exception |
Additionally, if you throw any exception implementing
PhlyRestfully\Exception\ProblemExceptionInterface, it can be used to seed an
ApiProblem instance with the appropriate information. Such an exception
needs to define the following methods:
- getAdditionalDetails(), which should return a string or array.
- getDescribedBy(), which should return a URI for the “describedBy” field.
- getTitle(), which should return a string for the “title” field.
The exception code and message will be used for the “httpStatus” and “detail”, respectively.
The CreationException, UpdateException, and PatchException types all
inherit from DomainException, which implements the
ProblemExceptionInterface.
As a quick example, let’s look at two listeners, one that listens on the
create event, and another on the fetch event, in order to see how we
might handle them.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | // listener on "create"
function ($e) {
$data = $e->getParam('data');
// Assume an ActiveRecord-like pattern here for simplicity
$user = User::factory($data);
if (!$user->isValid()) {
$ex = new CreationException('New user failed validation', 400);
$ex->setAdditionalDetails($user->getMessages());
$ex->setDescibedBy('http://example.org/api/errors/user-validation');
$ex->setTitle('Validation error');
throw $ex;
}
$user->persist();
return $user;
}
// listener on "fetch"
function ($e) {
$id = $e->getParam('id');
// Assume an ActiveRecord-like pattern here for simplicity
$user = User::fetch($id);
if (!$user) {
$ex = new DomainException('User not found', 404);
$ex->setDescibedBy('http://example.org/api/errors/user-not-found');
$ex->setTitle('User not found');
throw $ex;
}
return $user;
}
|
Typically, you will create a Zend\EventManager\ListenerAggregateInterface
implementation that will contain all of your listeners, so that you can also
compose in other classes such as data mappers, a service layer, etc. Read about
listener aggregates in the ZF2 documentation
if you are unfamiliar with them.
In a later section, I will show you how to wire your listener aggregate to a resource and resource controller.