• Час читання ~3 хв
  • 08.11.2022

Протягом багатьох років, як розробники, ми завжди шукали способи автоматизації нашої документації, від PHPDoc до Swagger і далі. За останні роки це стало значним зрушенням у світі API, щоб прийняти підхід до документації API, який більше орієнтований на дизайн. Головним чином це було викликано створенням специфікації OpenAPI, яка є заміною для Swagger.

Ми, як розробники, часто не маємо часу чи бажання занурюватися в підхід до наших API, який орієнтований на першочергове проектування – це просто факт. Хоча це може бути найкращою практикою, і те, що всі говорять. Насправді нам платять за створення та доставку функцій, тому ми часто пропускаємо кроки. Що, якби я сказав вам, що ви можете додати один маленький крок до свого робочого процесу, який дозволить вам створювати документацію API по ходу роботи?

Давайте розпочнемо. У цьому підручнику я буду створювати абсолютно вигаданий API без будь-якої мети, і це не буде так, як я буду зазвичай створювати API. Але це недаремно, оскільки я хочу, щоб ви зосередилися виключно на моїх кроках.

Я не буду проходити початкові кроки налаштування, оскільки це було багато розглянуто в минулому. У цьому підручнику я зроблю багато припущень – здебільшого про те, як ви знаєте, як налаштувати та інсталювати Laravel, а також про використання artisan для створення класів.

У нас є проект Laravel, відкритий у нашій IDE, і нам потрібно додати деякі функції. Я вважаю корисним під час створення API оцінити призначення API. Спробуйте зрозуміти, для чого це будується і для чого. Це дозволяє нам зрозуміти, що буде корисним для нашого API, і запобігає додаванню нових кінцевих точок, які просто непотрібні.

We will be building a simple книгиhelf API in this tutorial. It will allow us to create some pretty basic functionality - so that we have a purpose for what we are building. This API aims at consumers who can connect to our API to manage their books. The most important thing to these users is a way to see their books and add books quickly. Згодом будуть доступні й інші функції, але завжди запускайте API з основною метою, яка потрібна кожному користувачеві.

Створіть нову модель, міграцію та фабрику для моделі Book. Це буде основна модель у нашому API. Атрибути, які вам потрібні для цієї моделі, не такі важливі для цього підручника, але я все одно пройдуся по них:

public function up(): void
{
    Schema::create('books', static function (Blueprint $table): void {
        $table->id();
 
        $table->string('title');
        $table->string('subtitle')->nullable();
        $table->text('description');
        $table->string('language');
 
        $table->unsignedBigInteger('pages');
 
        $table->json('authors');
        $table->json('categories');
        $table->json('images');
        $table->json('isbn');
 
        $table->date('published_at');
        $table->timestamps();
    });
}

Це певною мірою відображає API книг Google. У нас є назва та підзаголовок книги, тобто її назва. Опис і мова пояснюють, про що книга і якою мовою. У нас є підрахунок сторінок, щоб визначити, чи велика це книга. Потім у нас є автори, категорії, зображення та ISBN, щоб додати додаткову інформацію. Нарешті, є опублікована дата.

Тепер, коли у нас є модель і база даних, ми можемо почати вивчати сам API. Нашим першим кроком буде встановлення пакета, який дозволить нам створити нашу документацію API. Є відмінний пакет, який називається Писар який можна використовувати, який працює як у Laravel, так і в простих програмах PHP. Ви можете встановити його за допомогою такої команди композитора:

composer require --dev knuckleswtf/scribe

Once you have installed this, you can follow the setup instructions to get this working within your application. Once this is installed, and the configuration is published - you can do a test run of the API doc generation to ensure it works as expected. You should get something like this out of the box:

openapi: 3.0.3
info:
  title: Laravel
  description: ''
  version: 1.0.0
servers:
  -
    url: 'http://localhost:8000'
paths: []
tags: []

Тепер, коли ми знаємо, що це працює, ми можемо додати кілька маршрутів, щоб забезпечити їх використання в генерації OpenAPI.

Давайте почнемо з наших перших маршрутів із пошуку книг, отримання списку книг і отримання однієї книги.

Route::prefix('books')->as('books:')->middleware(['api'])->group(static function (): void {
    Route::get(
        '/',
        App\Http\Controllers\Api\Books\IndexController::class,
    )->name(
        name: 'index',
    );
 
    Route::get(
        '{book}',
        App\Http\Controllers\Api\Books\ShowController::class,
    )->name(
        name: 'show',
    );
});

У нас є два маршрути під books префікс, і обидва є ОТРИМАТИ маршрути, які не потребують автентифікації. Вони будуть частиною загальнодоступного API, доступ до якого матиме кожен.

Зараз у нас є маршрути та диспетчери. Нам потрібно подумати, як ми хочемо керувати цими маршрутами. Ми хочемо відсортувати та відфільтрувати наші запити, щоб ми могли запитувати конкретні списки книг. Щоб досягти цього, ми будемо використовувати Конструктор запитів Space Laravel пакет, що забезпечує чистий інтерфейс для пошуку та фільтрації того, що нам потрібно. Давайте встановимо це за допомогою такої команди композитора:

composer require spatie/laravel-query-builder

Once this has been installed, we will be able to think about how to filter our API requests to get the correct list of books. With all good APIs, there is pagination. To achieve this, we could use the built-in paginator from Laravel. However, Aaron Francis created a paginator called Fast Paginate which is much more performant - something important when it comes to an API. You can install this using the following composer command:

composer require hammerstone/fast-paginate

Давайте об’єднаємо ці дві речі, щоб ми могли створити колекцію та повернути розбитий на сторінки результат.

return QueryBuilder::for(
    subject: Book::class,
)->allowedFilters(
    filters: ['language', 'pages', 'published_at'],
)->fastPaginate();

Це добре працює для нашого випадку використання, однак я не прихильник повернення результатів запиту безпосередньо з вашого API. Ми завжди маємо перетворювати відповідь за допомогою ресурсу API у контрольований формат. Laravel має вбудовані ресурси, або ви можете скористатися Фрактал ліг PHP пакет, який досить хороший. У цьому прикладі я буду використовувати пакет, який у мене є написано раніше, тому я не буду вдаватися в подробиці. Зрештою, ми повинні отримати контролер, який виглядає наступним чином або принаймні дуже схожий на нього:

final class IndexController
{
    public function __invoke(Request $request): JsonResponse
    {
        return new JsonResponse(
            data: BookResource::collection(
                resource: QueryBuilder::for(
                    subject: Book::class,
                )->allowedFilters(
                    filters: ['language', 'pages', 'published_at'],
                )->fastPaginate(),
            ),
        );
    }
}

Поки що це лише зареєструє наш маршрут у специфікації OpenAPI, що краще, ніж нічого. Але за допомогою додаткової роботи ми можемо задокументувати параметри та згрупувати речі, маючи набагато більше сенсу. У Scribe ви можете зробити це за допомогою DocBlocks або Attributes. Я вважаю за краще використовувати для цього DocBlocks, оскільки немає атрибутів для всіх полів, які ви хотіли б використовувати. Дозвольте мені показати вам приклад, і я розповім вам усе, що я зробив.

final class IndexController
{
    /**
     * @group Book Collection
     *
     * Get all Books from the API.
     *
     * @queryParam filter[language] Filter the books to a specific language. filter[language]=en
     * @queryParam filter[pages] Filter the books to those with a certain amount of pages. filter[pages]=1000
     * @queryParam filter[published_at] Filter the books to those published on a certain date. filter[published_at]=12-12-1992
     *
     */
    public function __invoke(Request $request): JsonResponse
    {
        return new JsonResponse(
            data: BookResource::collection(
                resource: QueryBuilder::for(
                    subject: Book::class,
                )->allowedFilters(
                    filters: ['language', 'pages', 'published_at'],
                )->fastPaginate(),
            ),
        );
    }
}

Починаємо з додавання @group Книгозбірня який згрупує цю кінцеву точку в «Колекції книг», що полегшить навігацію вашою документацією API. Потім ми додаємо «Отримати всі книги з API». який описує конкретну кінцеву точку. Тоді ми можемо додати додаткові @queryParam записи для документування доступних параметрів запиту, які приймає ця кінцева точка. Набагато простіше, ніж писати YAML, так!

У документації Scribe міститься набагато більше інформації, і ви можете детально ознайомитися з інформацією, яку ви додаєте. Я лише окреслив основи, але ви вже бачите, наскільки це може бути корисним. Що ви використовуєте для своєї документації API? Повідомте нас у Twitter!

Comments

No comments yet
Yurij Finiv

Yurij Finiv

Full stack

Про мене

Professional Fullstack Developer with extensive experience in website and desktop application development. Proficient in a wide range of tools and technologies, including Bootstrap, Tailwind, HTML5, CSS3, PUG, JavaScript, Alpine.js, jQuery, PHP, MODX, and Node.js. Skilled in website development using Symfony, MODX, and Laravel. Experience: Contributed to the development and translation of MODX3 i...

Про автора CrazyBoy49z
WORK EXPERIENCE
Контакти
Ukraine, Lutsk
+380979856297