Validations

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

Actions are the actual logic that is executed when a request is made to the API. Actions are the central logic for the entire app. They are responsible for handling the request, processing the data, and returning the response.

In Pionia, actions MUST be defined in services. If you haven’t created a service yet, you can check out the services documentation.

Creating an Action

In Pionia, an action is a method in a service class. To create an action, you need to create a method in the service class. The method should be public and should have the Action suffix such as loginAction.

Here is an example of an action in a service class:


namespace Application\Services;

use Pionia\Http\Services\Service;
use Pionia\Collections\Arrayable;

class UserService extends Service
{
    public function loginAction(Arrayable $data)
    {
        // Your logic here 
    }
}

In the above example, we have created a loginAction method in the UserService class. The method takes an Arrayable object as a parameter. The Arrayable object contains the data sent in the POST request body.

You can define other helper methods in the service class to help with the logic in the action method. Anything that is not suffixed with Action is considered a helper method and is not accessible via the API as an endpoint.

Request and Response

The action method takes an Arrayable object as a parameter. The Arrayable object contains the data sent in the request body. You can access the data using the get method of the Arrayable object.

Request Action

To define an action being targeted in your request, you have to specify the ACTION or action key in the request body. The value of the ACTION key should be the name of the action method in the service class.

Here is an example of a request body:

Assuming we have an action loginAction in the UserService class, the request body should look like this:

{
    "ACTION": "login"
}

The above can also be targeted like this:-

{
    "action": "login-action"
}

Or by simply the actual method name as the action:-

{
    "ACTION": "loginAction"
}

Accessing Request Data

Request data comes in various formats such as JSON, form data, etc. The Arrayable object provides a unified way to access the data regardless of the format.

get($key, $default = null)

Since the request data is received as a Pionia Collections Arrayable object, you can access the data using the get method. The get method takes two parameters: the key of the data you want to access and the default value to return if the key is not found.

Given the request data:-

{
    "username": "john.doe",
    "password": "password",
    "action": "login"
}

We can access the username and password fields in our action as follows:

namespace Application\Services;

use Pionia\Http\Services\Service;
use Pionia\Collections\Arrayable;

class UserService extends Service
{
    public function loginAction(Arrayable $data)
    {
        $username = $data->get('username');
        $password = $data->get('password');

        // Your logic here
    }
}

The get method also takes on an optional second parameter which is the default value to return if the key is not found. For example, if the limit key is not found in the request data below, the get method will return assign it to 10.

namespace Application\Services;

use Pionia\Http\Services\Service;
use Pionia\Collections\Arrayable;

class UserService extends Service
{
    public function loginAction(Arrayable $data)
    {
        $limit = $data->get('limit', 10);

        // Your logic here
    }
}

You can henceforth use $limit in your logic without expecting any null values.

getOrThrow($key, Throwable|string|null $exception = null)

This method is similar to the get method but throws an exception if the key is not found in the request data. The getOrThrow method takes two parameters: the key of the data you want to access and an optional exception to throw if the key is not found. If no exception is provided, a normal php Exception is thrown with the message $key not found.

This operation also prevents the code below from executing if the key is not found.

namespace Application\Services;

use Pionia\Http\Services\Service;
use Pionia\Collections\Arrayable;

class UserService extends Service
{
    public function loginAction(Arrayable $data)
    {
        $username = $data->getOrThrow('username');
        $password = $data->getOrThrow('password', new Exception('Password cannot be empty'));

        // Your logic here
    }
}

This ensures that you do not proceed with null values in your logic.

getString($key)

This returns the value of the key as a string or null. If the value is not a string, it is cast to a string.

namespace Application\Services;

use Pionia\Http\Services\Service;
use Pionia\Collections\Arrayable;

class UserService extends Service
{
    public function loginAction(Arrayable $data)
    {
        $username = $data->getString('username');
        $password = $data->getString('password');

        // Your logic here
    }
}

getInt($key)

This returns the value of the key as an int or null. If the value is not an integer, it is cast to an integer.


namespace Application\Services;

use Pionia\Http\Services\Service;
use Pionia\Collections\Arrayable;

class UserService extends Service
{
    public function loginAction(Arrayable $data)
    {
        $age = $data->getInt('age');

        // Your logic here
    }
}

getFloat($key)

This returns the value of the key as a float or null. If the value is not a float, it is cast to a float.

namespace Application\Services;

use Pionia\Http\Services\Service;
use Pionia\Collections\Arrayable;

class UserService extends Service
{
    public function loginAction(Arrayable $data)
    {
        $price = $data->getFloat('price');

        // Your logic here
    }
}

getBool($key)

This returns the value of the key as a bool or null. If the value is not a boolean, it is cast to a boolean.

namespace Application\Services;

use Pionia\Http\Services\Service;
use Pionia\Collections\Arrayable;

class UserService extends Service
{
    public function loginAction(Arrayable $data)
    {
        $is_active = $data->getBool('is_active');

        // Your logic here
    }
}

getJson($key)

This returns the value of the key as a json or null. If the value is not a json, it is cast to a json.

namespace Application\Services;

use Pionia\Http\Services\Service;
use Pionia\Collections\Arrayable;

class UserService extends Service
{
    public function loginAction(Arrayable $data)
    {
        $json = $data->getJson('json');

        // Your logic here
    }
}

getArray($key)

This returns the value of the key as an array or null. If the value is not an array, it is cast to an array.

namespace Application\Services;

use Pionia\Http\Services\Service;
use Pionia\Collections\Arrayable;

class UserService extends Service
{
    public function loginAction(Arrayable $data)
    {
        $array = $data->getArray('array');

        // Your logic here
    }
}

getArrayable($key)

This returns the value of the key as an Arrayable object or null. If the value is not an array, it is cast to an array.

namespace Application\Services;

use Pionia\Http\Services\Service;
use Pionia\Collections\Arrayable;

class UserService extends Service
{
    public function loginAction(Arrayable $data)
    {
        $arrayable = $data->getArrayable('arrayable');

        // Your logic here
    }
}

getA($key, $className)

This returns the value of the key as an object of the specified class. If the value is not an object of the specified class, an exception is thrown.

namespace Application\Services;

use Pionia\Http\Services\Service;
use Pionia\Collections\Arrayable;

class UserService extends Service
{
    public function loginAction(Arrayable $data)
    {
        $user = $data->getA('user', User::class);

        // Your logic here
    }
}

getPositiveInteger($key)

This returns the value of the key as a positive integer or null. If the value is not a positive integer, an exception is thrown.

namespace Application\Services;

use Pionia\Http\Services\Service;
use Pionia\Collections\Arrayable;

class UserService extends Service
{
    public function loginAction(Arrayable $data)
    {
        $age = $data->getPositiveInteger('age');

        // Your logic here
    }
}

getNegativeInteger($key)

This returns the value of the key as a negative integer or null. If the value is not a negative integer, an exception is thrown.

namespace Application\Services;

use Pionia\Http\Services\Service;
use Pionia\Collections\Arrayable;

class UserService extends Service
{
    public function loginAction(Arrayable $data)
    {
        $age = $data->getNegativeInteger('age');

        // Your logic here
    }
}

All methods available in the Arrayable class can be found here.

Request Files

If the request contains files, you can access them from the second parameter of the action method. The second parameter is an instance of the Symfony\Component\HttpFoundation\FileBag class from Symfony components.

Here is an example of how to access files in an action method:


namespace Application\Services;

use Pionia\Http\Services\Service;
use Pionia\Collections\Arrayable;

class UserService extends Service
{
    public function loginAction(Arrayable $data, FileBag $files)
    {
        $avatar = $files->get('avatar');

        // Your logic here
    }
}

The above $avatar variable will return an instance of Symfony\Component\HttpFoundation\File\UploadedFile which you can use to check and interact with files as you see fit.

Further Request Validation

Pionia provides a way to validate the request data before proceeding with the logic in the action method.

Various helper methods are available to help you achieve this. Let’s break down some of them below.

requires(string | array $keys)

The requires method is used to validate that the request data contains the specified key[s]. The requires method takes a string or an array of keys to validate.

If the request data does not contain the specified keys, an exception is thrown with the message Field $field is required!.

All keys must be present in the request data for the action to proceed.

validate(string $key, Arrayable | Request | Service $requestData)

The validate helper method exposes multiple other validators that you can use to validate the request data. The validate method takes two parameters: the key of the data you want to validate and an instance of Arrayable | Request | Service.

Here is an example of how to use the validate helper:


namespace Application\Services;

use Pionia\Http\Services\Service;
use Pionia\Collections\Arrayable;

class UserService extends Service
{
    public function loginAction(Arrayable $data)
    {
        validate('email', $this)->string()->email();
        // above is similar to below
        validate('email', $this)->string()->asEmail();

        // Your logic here
    }
}

You can find a complete list of validators here.