Sorry, I 'm a bit late …
Your setup is quite easy and creates a simple REST controller that will work. But this implementation does not use a single advantage of the API tools. No validation, no content matching, no automatic handling of request and return headers. You literally do everything by hand here. There is absolutely no need for that.
Here is a small example of how you install and configure only the code base and not the admin UI.
First install the API Tools meta module:
$ composer require laminas-api-tools/api-tools
$ composer update
After the installation edit your config/application.config.php
or config/modules.config.php
file. Add the module under the module
key.
'modules' => [
/* ... */
'Laminas\ApiTools',
],
From now on you can programmatically define your resources and api endpoints. Even some basic authentication listeners are implemented in the base config of laminas-api-tools/api-tools
. The following steps describe, how to define an endpoint in your module.config.php
file of your application.
Routing
The routing is like normal routing. You did that already with your implementation. Just write a router configuration in your application config config/module.config.php
.
return [
...
'router' => [
'routes' => [
'application.rest.user' => [
'type': \Laminas\Router\Http\Segment::class,
'options' => [
'route' => '/user[/:user_id]',
'defaults' => [
'controller' => 'Application\\V1\\Rest\\User\\Controller',
],
],
],
],
],
...
];
Of course, you could try to make the route more dynamic so that you don’t have to make a separate router entry for each resource. In this example, however, we will keep it very simple and assume that there is a route entry for each existing resource.
Versioning
API Tools ship a version control with laminas-api-tools/api-tools-versioning
. For how to configure the access to a specific version of your API resources just have a look at the versioning documentation. For our purpose we just use the uri
key for routes, that can have a [/v:version]
in it 's route.
...
'api-tools-versioning' => [
'uri' => [
'application.rest.user',
],
],
...
Rest Configuration
Since laminas-api-tools/api-tools
installed the dependency module laminas-api-tools/api-tools-rest
we can easily define our rest service. Just add the api-tools-rest
key to your config/module.config.php
of your application.
...
'Application\\V1\\Rest\\User\\Controller' => [
'listener' => \Application\V1\Rest\User\UserResource::class,
'route_name' => 'application.rest.user',
'route_identifier_name' => 'user_id',
'collection_name' => 'user',
'entity_http_methods' => [
0 => 'GET',
1 => 'PATCH',
2 => 'PUT',
3 => 'DELETE',
],
'collection_http_methods' => [
0 => 'GET',
1 => 'POST',
],
'collection_query_whitelist' => [],
'page_size' => 25,
'page_size_param' => null,
'entity_class' => \Application\V1\Rest\User\UserEntity::class,
'collection_class' => \Application\V1\Rest\User\UserCollection::class,
'service_name' => 'User',
],
...
These settings define some major points for your rest service. Under the listener
key you define the resource class. With every call of the defined route route_name
this class will be dispatched to handle all entity or collection requests. As you can see you don 't need a controller class for your REST service. All will be handled in the class we mentioned under the listener
key. For a full description of all available user config keys have a look at the github repository.
Content negotiation
Attention! At this point, we’ll get into the topic of your interface’s security a bit. Here we define which controller should respond with which type and what media types are accepted. Like all other configuration just add this to your application config/module.config.php
file.
...
'api-tools-content-negotiation' => [
'controllers' => [
'Application\\V1\\Rest\\User\\Controller' => 'Json',
],
'accept_whitelist' => [
'Application\\V1\\Rest\\User\\Controller' => [
'application/vnd.my-api-name.v1+json',
'application/json',
'application/*+json',
],
],
'content_type_whitelist' => [
'Application\\V1\\Rest\\User\\Controller' => [
'application/vnd.my-api-name.v1+json',
'application/json',
],
],
],
...
From my point of view, the settings are enormously important in terms of security. Hereby you ensure which Accept Header information and which Content Type is accepted by your API. Everything that does not match these settings will be answered with a 406 Not Accetbale or a 415 Unsupported Media Type. For a complete list of content negotiation settings have a look at the respective github repository.
Content Validation
In this example we define a user service. This service can deal with POST
and PUT
/PATCH
requests for creating or updating data sets. The good old principle “never trust user data” forces us to validate the received data as strictly as possible. For this we use the input filters and validators from the Laminas framework. You might know that from laminas/laminas-form
. It 's quite identical when dealing with API tools. As always add the following code to your applications config/modules.config.php
.
...
'api-tools-content-validation' => [
'Application\\V1\\Rest\\User\\Controller' => [
'input_filter' => 'Application\\V1\\Rest\\\User\\Validator',
],
],
'input_filter_specs' => [
'Application\\V1\\Rest\\\User\\Validator' => [
[
'name' => 'id',
'required' => false,
'filters' => [ ... ],
'validators' => [ ... ],
],
],
],
...
This is the simplest form of adding content validation. You can define a single input filter spec for every http method allowed for your service. For a deeper understanding have a look at the configuration specs in the github respository.
Authorization
The laminas-api-tools/api-tools
module also installed the laminas-api-tools/api-tools-mvc-auth
module. This module provides services, event listener and configuration for handling authentication and authorization. There are different ways of authentication: Bais authentication, Digest authentication and OAuth2 authentication. There is no simple way of just logging in to an existing user account. Common APIs do not work that way. I personally prefer the OAuth2 way. It 's secury and widely known.
Authentication can be pretty complex. All you have to know is well written down in the github repository documentation.
Conclusion
If you want an easy to setup API based on Laminas API Tools I strongly recommend using the laminas-api-tools/api-tools-skeleton
repository. It 's easy to use and well documented. Creating an API isn 't just about setting up a restful controller and trying to respond with the right http status codes. As you can see above, there 's a lot more to recognize.
Considering the development time you need to programmatically recreate all of this, it clearly makes more sense from my point of view to simply use the ready-made UI, through which you can set up REST and RPC services in a relatively short time. There are good tutorials on how to implement authentication and the associated authorization. At the risk of repeating myself, just use the admin UI and read the tutorials. It’s not going to get any easier.