Courses

How to Build Laravel 12 API From Scratch

Generating API Documentation with Scribe

Summary of this lesson:
- Installing and configuring Scribe for API documentation
- Customizing documentation
- Adding endpoint descriptions and parameters using docblocks/attributes

In this lesson, we will talk about API documentation and how to generate it. This lesson will use Scribe to auto-generate documentation. At the end, we will have a similar page to the image below:


We can install Scribe via composer with the --dev flag because this package is for a development environment. And then publish the config file.

composer require --dev knuckleswtf/scribe
php artisan vendor:publish --tag=scribe-config

By default, Scribe is set to use all the routes under the /api prefix. This setting is set in the config/scribe.php under the routes.match.prefixes key.

Now, we can generate the documentation using an artisan command.

php artisan scribe:generate

After running the generate command in the terminal, we see that the package went through all routes and generated docs in the public/docs directory.

Now, you can visit /docs in the browser and should see the generated documentation.

After installing the package and running the generate command, we made an API documentation page. Also, for example, for the api/categories endpoint as an example response, we have real data taken from a database. When generating, Scribe goes through all the endpoints and tries to launch them, and the response is shown in the example.

This is how you can generate API documentation for yourself or the frontender.


Now, let's look at some of the customizations that can be done. First, we can configure an introduction text and logo.

config/scribe.php:

<?php
 
use Knuckles\Scribe\Extracting\Strategies;
 
return [
// ...
 
'intro_text' => <<<INTRO
This documentation aims to provide all the information you need to work with our API. // [tl! --]
This documentation aims to provide all the information you need to work with our E-Shop API. // [tl! ++]
 
<aside>As you scroll, you'll see code examples for working with the API in different programming languages in the dark area to the right (or as part of the content on mobile).
You can switch the language used with the tabs at the top right (or from the nav menu at the top left on mobile).</aside>
INTRO
,
 
// ...
 
'logo' => '',
'logo' => 'https://demo-eshop-bootstrap.filamentexamples.com/storage/logo.png',
 
// ...
];

After every change, you need to regenerate.

php artisan scribe:generate

Let's rename endpoints from api/categories to Get Categories.

We can rename it in two ways. The first one uses docblock, and the second uses PHP attributes in the Controller.

The docblock version:

app/Http/Controllers/Api/CategoryController.php:

class CategoryController extends Controller
{
/**
* Get Categories
*
* Getting the list of the categories
*/
public function index()
{
return CategoryResource::collection(Category::all());
}
 
// ...
}

The PHP attributes version:

app/Http/Controllers/Api/CategoryController.php:

use Knuckles\Scribe\Attributes\Endpoint;
 
class CategoryController extends Controller
{
#[Endpoint('Get Categories', <<<DESC
Getting the list of the categories
DESC)]
public function index()
{
return CategoryResource::collection(Category::all());
}
 
// ...
}

Next, we can group endpoints into menu items. This can also be done using docblock and PHP attributes.

Docblock version:

app/Http/Controllers/Api/CategoryController.php:

 
/**
* @group Categories
*
* Managing Categories
*/
class CategoryController extends Controller
{
// ...
}

app/Http/Controllers/Api/ProductController.php:

 
/**
* @group Products
*
* Managing Products
*/
class ProductController extends Controller
{
// ...
}

PHP attributes version:

app/Http/Controllers/Api/CategoryController.php:

use Knuckles\Scribe\Attributes\Group;
 
#[Group('Categories', 'Managing Categories')]
class CategoryController extends Controller
{
// ...
}

app/Http/Controllers/Api/ProductController.php:

use Knuckles\Scribe\Attributes\Group;
 
#[Group('Products', 'Managing Products')]
class ProductController extends Controller
{
// ...
}

Now we have categories and products under their menu item, and everything else is under the endpoints.

URLs often have query parameters—for example, a page parameter.

The docblock version:

app/Http/Controllers/Api/CategoryController.php:

class CategoryController extends Controller
{
/**
* Get Categories
*
* Getting the list of the categories
*
* @queryParam page Which page to show. Example: 12
*/
public function index()
{
return CategoryResource::collection(Category::all());
}
 
// ...
}

The PHP attributes version:

app/Http/Controllers/Api/CategoryController.php:

use Knuckles\Scribe\Attributes\QueryParam;
 
class CategoryController extends Controller
{
#[Endpoint('Get Categories', <<<DESC
Getting the list of the categories
DESC)]
#[QueryParam('page', 'int', 'Which page to show.', example: 12)]
public function index()
{
return CategoryResource::collection(Category::all());
}
 
// ...
}

It also adds a parameter to the example request.

Now, for the POST request, let's add body parameters.

Docblock version:

app/Http/Controllers/Api/CategoryController.php:

class CategoryController extends Controller
{
// ...
 
/**
* POST categories
*
* @bodyParam name string required Name of the category. Example: "Clothing
*/
public function store(StoreCategoryRequest $request)
{
// ...
}
 
// ...
}

PHP attributes version:

app/Http/Controllers/Api/CategoryController.php:

class CategoryController extends Controller
{
// ...
 
#[BodyParam('name', 'string', 'Name of the category.', true, 'Clothing')]
public function store(StoreCategoryRequest $request)
{
// ...
}
 
// ...
}

As in the query parameters example, the name is now required instead of optional.

For more, check the official Scribe documentation.

Previous: Authentication with Laravel Passport and Password Grant Type
avatar

In case when you have problem with composer require --dev knuckleswtf/scribe use it with --with-all-dependencies

avatar

What problem did you have? Maybe package got outdated

avatar

Your requirements could not be resolved to an installable set of packages.

Problem 1 - knuckleswtf/scribe[1.0.0, ..., 1.6.0] require illuminate/console ^5.8|^6.0|^7.0 -> found illuminate/console[v5.8.0, ..., v5.8.36, v6.0.0, ..., v6.20.44, v7.0.0, ..., v7.30.6] but these were not loaded, likely because it conflicts with another require. - knuckleswtf/scribe 1.7.0 requires illuminate/console ^5.8|^6.0|^7.0|^8.0 -> found illuminate/console[v5.8.0, ..., v5.8.36, v6.0.0, ..., v6.20.44, v7.0.0, ..., v7.30.6, v8.0.0, ..., v8.83.27] but these were not loaded, likely because it conflicts with another require. - knuckleswtf/scribe[1.8.0, ..., 1.9.1] require illuminate/console 5.8.*|^6.0|^7.0|^8.0 -> found illuminate/console[v5.8.0, ..., v5.8.36, v6.0.0, ..., v6.20.44, v7.0.0, ..., v7.30.6, v8.0.0, ..., v8.83.27] but these were not loaded, likely because it conflicts with another require. - knuckleswtf/scribe[2.0.0, ..., 2.7.10, 3.0.0, ..., 3.21.0] require illuminate/console ^6.0|^7.0|^8.0 -> found illuminate/console[v6.0.0, ..., v6.20.44, v7.0.0, ..., v7.30.6, v8.0.0, ..., v8.83.27] but these were not loaded, likely because it conflicts with another require. - knuckleswtf/scribe[3.22.0, ..., 3.37.2] require illuminate/console ^6.0|^7.0|^8.0|^9.0 -> found illuminate/console[v6.0.0, ..., v6.20.44, v7.0.0, ..., v7.30.6, v8.0.0, ..., v8.83.27, v9.0.0, ..., v9.52.16] but these were not loaded, likely because it conflicts with another require. - knuckleswtf/scribe[4.0.0, ..., 4.13.0] require illuminate/console ^8.0|^9.0 -> found illuminate/console[v8.0.0, ..., v8.83.27, v9.0.0, ..., v9.52.16] but these were not loaded, likely because it conflicts with another require. - knuckleswtf/scribe[4.14.0, ..., 4.29.0] require nikic/php-parser ^4.10 -> found nikic/php-parser[v4.10.0, ..., v4.18.0] but the package is fixed to v5.0.0 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command. - Root composer.json requires knuckleswtf/scribe * -> satisfiable by knuckleswtf/scribe[1.0.0, ..., 1.9.1, 2.0.0, ..., 2.7.10, 3.0.0, ..., 3.37.2, 4.0.0, ..., 4.29.0].

avatar

Seems like there is problem with the package. Add "knuckleswtf/scribe": "^4.29", manually to the composers require-dev and run composer update

avatar
You can use Markdown
avatar
You can use Markdown