API Tutorial
On this page
- Out Target
- Prerequisites
- Step 1: Initialize the project
- Step 2: Connect to a database
- Step 3: Create your first service -
TodoService
- Step 4: Create or update a to-do item in the database - 1st action.
- Step 5: Retrieve all to-do items from the database - 2nd action.
- Step 6: Retrieve a single to-do item from the database - 3rd action.
- Step 7: Grab n random to-do item[s] from the database - 7th action.
- Step 8: Delete a to-do item from the database - 5th action.
- Post Tutorial – What Next?
This section assumes that you have already setup your Pionia framework project. If you haven’t done that, please head over to Installation section for details.
This guide also introduces you to the implementation of the Moonlight architecture, so you can check it out first to get familiar with the terminologies.
Out Target
We should be able to accomplish the following tasks by the end of this tutorial:
- Initialize the project.
- Connect to a database.
- Create your first service.
- Create or update a to-do item in the database.
- Retrieve all to-do items from the database.
- Retrieve a single to-do item from the database.
- Retrieve n random to-do item[s] from the database.
- Delete a to-do item from the database.
Prerequisites
- You should have a basic understanding of PHP.
- You should have postman installed on your machine for testing the API.
- You should have a database created already.
Step 1: Initialize the project
To create a new project, you need to run the following command in the directory you want your project to be created. We are calling ours todo_api
.
We can open the project in our favorite code editor or IDE, for this tutorial we will be using PhPStorm IDE.
All IDEs and Editors should be supported for use since Pionia is powered by PHP that is supported by most of the IDEs.
For explanation of the directories and scripts, please refer to the Structure Section of this documentation.
To confirm that our installation works fine, let’s just go start our server. Open the terminal in the root of the project and run the following command.
If everything is setup correctly, your project should be up and running on http://127.0.0.1:8000. Visiting this url, you should see the following page.
We can test if our APIs are also working fine by visiting http://127.0.0.1:8000/api/v1/. It should return the following in the browser.
- Initialize the project(Completed)
Step 2: Connect to a database
Pionia removes the section of models and migrations and instead uses a simple and lightweight query builder to interact with the database - PORM.
At its heart, PORM was initially a wrapper on top of medoo, a lightweight database framework that makes interacting with the database easy and fun.
However, from v2.0^
, the core medoo package was re-written to meet Pionia-specific needs and added to the core Pionia.
You can create a new database or use an existing one as you see fit!
Assuming you have already setup your MySQL / MariaDB database.
Let’s first create our database as below:
Let’s use / specify todo_db
database created above:
Let’s create a table called todos
as below:
Let’s see the table created as todos
in the database todo_db:
Let’s describe the table created as todos
:
Above should return the following:
Let’s list all items in the todos
table:
Database configurations in the environment
folder should be done in any .ini
files.
You can create a dedicated environment/database.ini
file or just use the existing environment/settings.ini
.
But why do we have have to do this from .ini
files?
Pionia supports connection to multiple database at ago. Using .ini
files, these can just be sections.
Forexample, our first database can called [db]
, and then our second can [db2]
. Pionia will auto-discover these
and collect them in the container
as needed. To set a database as the default, just add default=1
or default=true
in its section.
Open settings.ini
file and update the database settings as below:
- Connect to a database(Completed)
Throughout this tutorial, we will be creating everything manually, however, pionia cli can be used to create most of the staff for you.
Just run the following command in your terminal to see the available commands. And you can always add your own commands like illustrated in this section
Step 3: Create your first service - TodoService
Since all our business logic is related to To-do items, we only need one service called TodoService
.
Points to ponder!
All Pionia services reside in the
services
folder under the namespace ofApplication\Services
.
All Pionia Services should extend
Service
fromPionia\Http\Services\Service
.
At its most minimal nature, this is a valid Pionia Service. For details about services, please through the detailed guide here
Service Registration - Switches.
Pionia introduces the concept of switches to help in api versioning. Be default, your new application already
consists of MainApiSwitch
which maps all requests targeting /api/v1/
.
When can create switches manually or via the cli, but all in all, these should only define one method registerServices
which returns
a Pionia Pionia\Collections\Arrayable
. In this Arrayable, you can register all your services that should be under the same version like /api/v1
.
For details, about switches, please head over to Service Registration section of services.
For now, let’s register our created service in the MainApiSwitch
class. Open MainApiSwitch.php
in the switches
folder and add the following code in our
registerServices
method.
Now our service is discoverable by the framework.
- Create the service(Completed)
Step 4: Create or update a to-do item in the database - 1st action.
Pionia Actions.
To their simplest, these are just class methods with a little sugar-coating. As we have already seen, Pionia services
are just PHP classes that extend from Service
. All methods defined in these services(classes) that are suffixed by
Action
and return Pionia\Http\Response\BaseResponse
, are taken to be Pionia Actions. Therefore, any other methods defined in Pionia Service without an Action
suffix are taken
to be just class methods not a Pionia Action.
For Details about Pionia Actions, please read more about the details here.
We create our first action in our service called ‘createOrUpdateAction’. This action will be responsible for creating a new to-do item in the database or update an existing one if an id is provided.
✨So, briefly to go through what we just did.
- We created our action which takes up a Pionia Arrayable
$data
which will always contain our POST request data. - We collected our data,
title
anddescription
as a string, theid
as an integer. - We checked if we actually have an
id
in our request. If no id was provided, we use the post data given to us to create a new todo, otherwise we updated the matched to-do. - Finally, we returned a response using one of our Pionia Helpers
Sending the request using any client of choice.
So, in the request, using the above, we defined that everytime we define a SERVICE
or service
called todo
, our TodoService
should then be loaded. Remember, all services are lazy-loaded, so, Pionia does not know that this service exists till it’s required by the incoming request.
For actions, the same process applies. All actions are lazy-loaded too.
But how do we then target our actions, a case here, createOrUpdateAction
?
To hit out action, another key called ACTION
or action
must be passed in our request post data.
This can target the action name directly as the method name:-
Or we can ignore the Action
suffix like this.
Or if you love snake_case format, you can also pass it like below
On Successful execution, the above code should return the following:
And in the database, we should have the following:
Before we proceed, let’s first understand what just happened above.
When you reached the endpoint http://localhost:8000/api/v1/
with the data as shown above, the request came via our public/index.php
, which loaded out routes. We only have one route as follows:-
The above route implies that all requests to http://localhost:8000/api/v1/
should be handled by the MainApiSwitch
switch.
The main api switch checks in the request body for the SERVICE
and ACTION
keys.
If they are not found, it throws an exception. If they are found, it maps the request to the service and action mentioned basing on the registered services.
Therefore, for your service to be discovered, you must register it as we did here.
So, after here, the service needed is loaded and the entire request in forwarded to it. When the service receives the request, it checks for the action mentioned in the request body. If the action is not found, it throws an exception. If the action is found, it executes the action and returns a response back to our client.
- Create or update a to-do item in the database(Completed)
Step 5: Retrieve all to-do items from the database - 2nd action.
We created our todo from the above step, please first take time to create as many as you want.
Now, let’s create an action called listAction
in our service to retrieve all to-do items from the database.
Now, let’s change our JSON in postman to the following:
Send the request and you should get the following response:
Point To Ponder
Notice how the returnData
is an array, yet it was an object in the previous response. returnData
and extraData
can be of any type, it is up to you to decide what to return in them.
You can also omit the message by setting it to null which should be logical for cases of listing items.
- Retrieve all to-do items from the database(Completed)
Step 6: Retrieve a single to-do item from the database - 3rd action.
We will create an action called retrieveAction
in our service to retrieve a single to-do item from the database.
Here we are going to test two scenarios, one is where everything goes smoothly and the other is where the server panics(throws an exception).
In the first scenario, we get back a status code of 200 OK with the following response.
But in the second scenario, we still get a status code of 200 OK but with the following response.
Point To Ponder
Notice how the exception message becomes our returnMessage
. This exception was caught by our switch. Therefore, wherever you’re in the services, feel free to throw any exceptions with clean messages.
- Retrieve a single to-do item from the database(Completed)
Step 7: Grab n random to-do item[s] from the database - 7th action.
You can keep hitting this action and on each hit, you should get a different to-do item. You can also play with the length
parameter to get more or less to-do items.
- Grab n random to-do item[s] from the database(Completed)
Step 8: Delete a to-do item from the database - 5th action.
If you followed along upto this far, you should be able to implement this on your own. If you get stuck, you can refer to the code below.
Change your request object to the following in your client(postman).
If you did everything right, you should get your response as follows
- Delete a to-do item from the database(Completed)
Point To Ponder
- All our requests are made via POST method.
- All our requests have similar body structure, they have a
SERVICE
,ACTION
, and other param keys. - All our responses have the same response format,
returnCode
,returnMessage
,returnData
, andextraData
keys. - We are hitting the same endpoint
http://localhost:8000/api/v1/
for all our requests. - We did not touch the routes or the kernel. but we only focused on the service!
This is the beauty of the Moonlight architecture. It makes it easy to understand and maintain your code.
Imagine how fast you would pull off a new service with Pionia.
Post Tutorial – What Next?
Deep Dive into Pionia Requests
Explore more features about the Pionia Requests and the request cycle.