Дополнительно/Расширения/Набор трейтов для создания API

Набор трейтов для создания API

Для реализации API на фреймворке HLEB2 предусмотрен набор трейтов, упрощающих валидацию и обработку данных в контроллерах (там, где эти трейты применены).

Применение трейтов в PHP является поводом для различных мнений, поэтому этот модуль вынесен в отдельную библиотеку, применять которую вы можете по желанию. Существует достаточно большой выбор валидаторов для разработки на PHP, данный лишь представляет простой работоспособный аналог.

Установка библиотеки github.com/phphleb/api-multitool при помощи Composer:

$composer require phphleb/api-multitool

или скачайте и распакуйте архив с библиотекой в папку /vendor/phphleb/api-multitool.


#Подключение трейта BaseApiTrait (набор трейтов)

Сначала нужно создать родительский класс BaseApiActions (или с другим названием) для контроллеров с API:

<?php
// File /app/Controllers/Api/BaseApiActions.php

namespace App\Controllers\Api;

use 
Hleb\Base\Controller;
use 
Phphleb\ApiMultitool\BaseApiTrait;

class 
BaseApiActions extends Controller
{
    
// Adding a set of traits for the API.
    
use BaseApiTrait;

    function 
__construct(array $config = [])
    {
        
parent::__construct($config);

        
// Passing the debug mode value to the API constructor.
        
$this->setApiBoxDebug($this->container->settings()->isDebug());
    }
}

Bсе вспомогательные трейты собраны в трейте BaseApiTrait как набор. Поэтому достаточно подключить его к контроллеру и получить полную реализацию. Если необходим другой набор из этих трейтов, то нужно или использовать их группой или соединить в собственный набор.

После этого во всех наследуемых от этого класса контроллерах появятся методы от каждого трейта в наборе:


#ApiHandlerTrait

Трейт ApiHandlerTrait содержит несколько методов, которые могут пригодиться для обработки возвращаемых данных API. Это не значит, что его методы 'present' и 'error' формируют окончательный ответ, они возвращают именованные массивы, которые можно использовать по собственному более сложному стандарту. Пример в методе контроллера:

<?php
// Файл /app/Controllers/Api/UserController.php

namespace App\Controllers\Api;
use 
App\Models\UserModel;
class 
UserController extends BaseApiActions
{
    public function 
actionGetOne(): array
    {
        
$id $this->container->request()->get('id')->asInt();
        if (!
$id) {
            return 
$this->error('Invalid request data: id'400);
        }
        
$data UserModel::getOne($id);
        return 
array_merge(
            
$this->present($data ?: []),
            [
'error_cells' => $this->getErrorCells()]
        );
    }
}

Во фреймворке HLEB при возвращении массива из контроллера он автоматически преобразуется в JSON. При выводе отформатированного массива к нему добавлено значение 'error_cells' с перечнем полей, в которых произошли ошибки валидации (при наличии таковых).


#ApiMethodWrapperTrait

Осуществляет перехват системных ошибок и вывод их в метод 'error' предыдущего трейта ApiHandlersTrait или иного, предназначенного для этой цели (если упомянутый трейт не используется). Если вызван метод контроллера, то для правильной обработки его ошибок необходимо добавить префикс 'action' в контроллере, а в маршруте оставить без префикса, как, например, для предыдущего примера контроллера роутинг будет примерно таким:

Route::get('/api/users/{id}')->controller(UserController::class, 'getOne');

Здесь нужно уточнить, что в оригинале вызов идёт к методу 'getOne' контроллера, а в самом контроллере метод 'actionGetOne'.


#ApiPageManagerTrait

Реализует довольно частно необходимую функцию пагинации выводимых данных. Добавляет метод 'getPageInterval', который преобразует данные пагинации в более удобный вид. При этом вычисляется начальное значение выборки, что удобно для работы с базой данных.


#ApiRequestDataManagerTrait

Добавляет метод 'check', при помощи которого можно проверить данные одного массива при помощи условий проверки из другого. Использование этого трейта добавляет возможность проверить любые входящие данные, преобразованные в массив, будь это параметры POST-запроса или JSON Body. Существует перечень возможных условий, при помощи которых можно проверить данные, они составляются разработчиком. Например (Request::input() для фреймворка HLEB2 возвращает массив JSON Body):

use Hleb\Static\Request;

$data Request::input();
// $result - a boolean value indicating whether the checks were successful or not.
$result $this->check($data,
    [
        
'id' => 'required|type:int|min:1'// Required field, type integer, minimum value 1.
        
'email' => 'required|type:string'// Required field, type string.
        
'name' => 'type:string,null'// Optional field, but will check for type string or NULL if found.
        
'password' => 'required|type:string|minlength:6' // Required field, type string, minimum number of characters 6.
    
]);
$errorCells $this->getErrorCells(); // An array with a list of fields that did not pass the check.
$errorMessage $this->getErrorMessage(); // An array with messages about validation errors that occurred.

required - обязательное поле, располагается строго в начале.

Список возможных типов ('type' - обязательно на первом месте или после required):
string - проверяет наличие строкового значения, ограничения могут быть minlength и maxlength.
float - проверка на тип float(double), ограничения могут быть max и min.
int - проверка на тип int(integer), ограничения могут быть max и min.
regex - проверка по регулярному выражению, например 'regex:[0-9]+'.
fullregex - проверка по полному регулярному выражению, аналогично 'fullregex:/^[0-9]+$/i', обязательно обрамлённое слешами, может содержать символы : и |, в отличие от более простого regex.
bool - проверка на булево значение, только true или false.
null - проверка на null как правильное значение.
void - проверка на пустую строку как правильное значение.

Тип для перечислений:
enum - поиск среди возможных значений, например 'enum:1,2,3,4,south,east,north,west'.
Проверка на равенство не строгая, поэтому правильно будет как 4, так и '4', для точного соответствия лучше сопроводить проверкой на тип.

Можно добавить два и более типа, они будут проверены на все общие условия включительно, например 'type:string,null,void|minlen:5' - будет означать, что проверяется строка, минимум 5 символов или пустая, или же значение null, во всех остальных случаях возвращает false как результат не пройденной проверки валидации.

Также можно проверить массив из поля со списком стандартных полей массива (будут проверяться по единому шаблону):

$result $this->check($data,
    [
        
// Optional field, array with enumeration (two fields are checked in each).
        
'users' => ['id' => 'required|type:int''name' => 'required|type:string'],
        
// Required field, array with enumeration (three fields are checked in each).
        
'images' => ['required', ['id' => 'required|type:int''width' => 'required|type:int''height' => 'required|type:int']]
    ]);

Для проверки значений вложенных массивов в проверочном массиве название указывается в квадратных скобках.

$result $this->check(
    [
        [
'name1' => ['name2' => ['name3' => 'text']]],// Data.
        
['[name1][name2][name3]' => 'required|type:string'// Array with conditions.
    
]);

Приведённое выше условие вернёт успешную проверку с учётом вложенности.


#Тестирование

Трейты API проверены при помощи github.com/phphleb/api-tests

Страница создана: @fomiash
К началу страницы