Services
This section assumes that you have a basic understanding of the Pionia framework. If you are new to Pionia, you can start with the tutorial.
Introduction
Services in Pionia Framework are central holders of business logic. This is where most of the work happens.
Pionia has tried to reduce your work from other areas so that you mainly focus on this essential area.
Services are in actual PHP code, just php classes that extend the BaseRestService
.
As you might already know, a class can have multiple methods. In Pionia we call these Actions
. Therefore, henceforth, the terms service
and actions
will be used for the same meaning throughout the same guide.
Creating a service
You can create a service using our pionia console or manually. All services, as a convention, must be located in the services
folder.
We recommend to name your services after your database tables. Example, if your table is called ‘users’, you can name your service ‘UserService’.
If you are using our ‘pionia console’, then you can just name your service ‘user’. These are just conventions!
Remember generic services target a base table.
Therefore, you shall be asked the table you want to target. This is required.
However, starting from version 1.1.7, you can target relationships too!
You can read more about this in the Generic Services Section.
Service Registration
Creating a service is not enough in Pionia. You also need to register it in our switcher to make it discoverable by the kernel. Service registration happens in the associated switch.
In the switches folder, find the switch you want to use for this service. You can add your service as below.
The key
of this method is the name you shall use in your proceeding requests to access this service. Therefore, it must be unique!
A single service can be registered in multiple switches. This is useful when you want to use the same service in different api versions.
Targeting a service in the request
In the request, you can target a service by determining the SERVICE
key with your service name as the key
defined in the registerServices
method.
Targeting a service action
To target an action in a certain service, you need to define both the service and action as below.
The action in every request should match the name of your method in your service action. Pionia uses auto-discovery to automatically call the method passing in every required data needed for the request.
The keys SERVICE
and ACTION
are reserved and should not be used for any other purpose in the request data.
The same keys are case-sensitive and should be in uppercase.
Request Data and Response
Accessing the Request object in the services
You can access the request object in your service by calling the $this->request
method on the service object. This returns the Pionia\Request\Request
object.
You can use this to access anything on the request.
Request Data
JSON and Form Request Data
An action takes $data
as the first parameter which is an array of the request data. You can access you post data from this parameter.
This consists of both JSON and form data. Therefore, you can access your data as below.
You can also access your request data from the $this->request
object.
You can also access the request method, headers, and other request data from the $this->request
object.
Multipart Data(Uploads)
If your action expects multipart upload files, then you can get these from the second action parameter called $files
.
This is an associative array of all uploads.
NOTE: This does not consist of base64 encoded uploads, for those, they’ll be part of the
$data
.
Action Response.
All actions must return a Pionia\Response\BaseResponse
object. This is the object that is sent back to the client. You can use the BaseResponse
object to send back a response with a status code, message, and data.
A helper method BaseResponse::JsonResponse
is provided to help you create a response object that is ready to be serialized to JSON.
For details about request and responses, you can check the request and response section.
Action protection
You can protect your actions by determining that they require only authenticated requests(users) to be accessed. You can do this in three ways.
Globally in the service
Entire service
You can mark an entire service as requiring authentication by setting the $serviceRequiresAuth
parameter to true
.
Specific actions
You can also mark specific actions in a service as requiring authentication. Use the $actionsRequiringAuth
parameter and add action names of actions that should be reached by authenticated users only.
This, unlike $serviceRequiresAuth
, will only protect the actions listed in the array not the entire service.
Internally in the action
You can also call the mustAuthenticate
method anywhere in your action, preferably the first line in the action method.
Details of how Pionia achieves authentication and authorization can be found in the authentication section.
Error Handling
According to Moonlight architecture, all requests should return a 200 Ok status code. This is because the client should
be able to know if the request was successful or not by checking the returnCode
in the response body.
All normal responses set this internally and are always returning a 200 status code. By convention and by default, all requests
that are successful return 0 as the returnCode
. This implies that the server can define multiple other return codes
for other scenarios.
In Pionia, we have a global exception handler that catches all exceptions thrown anywhere in the code. This is to ensure that the client always gets the same response format.
All exceptions thrown are caught will raise a 500 status code and the message of the exception will be sent back to the client
as the returnMessage
.
Therefore, in your services and actions, you can throw exceptions as you see fit. And you don’t need to catch them at all!
Please note that all exceptions are caught globally and sent back to the client. Therefore, you do not need to catch exceptions in your services. Developers need to set clean, descriptive exception messages in their exceptions to help the client understand what went wrong.
Deactivating actions in a service
BaseRestService provides a parameter $deactivatedActions
that can be used to register all deactivated actions in a service.
This is useful when you want to deactivate an action in a service without deleting it.
Deactivated actions will not be called by the switcher. Therefore, they will not be accessible by the client.