Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.apivalk.com/llms.txt

Use this file to discover all available pages before exploring further.

The Problem

In Apivalk, request data is populated into bags. While you can access data using $request->getBody()->get('name'), the framework also supports magic getters like $request->name. Without extra metadata, IDEs (like PhpStorm) won’t know that name exists or what type it is.

The Solution: Automated DocBlocks

The DocBlockGenerator automates the creation of this metadata. It performs the following steps for every Request class in your project:
  1. Discovery: Scans your API directories for classes extending AbstractApivalkController.
  2. Extraction: Executes the getRequestClass() and getRoute() methods on the Controller to find the associated Request class and its properties.
  3. Shape Generation: Creates “Shape” classes (e.g., GetUserBodyShape, GetUserSortingShape, GetUserFilteringShape) in a Shape/ subdirectory. These classes contain public properties representing your documentation and route-defined sorting/filtering.
  4. Rewrite: Updates the original Request class file with @method tags pointing to these Shape classes.

Example Result

Before running the generator, your Request class might look like this:
class GetUserRequest extends AbstractApivalkRequest {
    // Empty class
}
After running DocBlockGenerator, it is automatically updated to:
/**
 * @method \apivalk\apivalk\Http\Request\Parameter\ParameterBag|Shape\GetUserQueryShape query()
 * @method \apivalk\apivalk\Http\Request\Parameter\ParameterBag|Shape\GetUserPathShape path()
 * @method \apivalk\apivalk\Http\Request\Parameter\ParameterBag|Shape\GetUserBodyShape body()
 * @method \apivalk\apivalk\Router\Route\Sort\SortBag|Shape\GetUserSortingShape sorting()
 * @method \apivalk\apivalk\Router\Route\Filter\FilterBag|Shape\GetUserFilteringShape filtering()
 * @method \apivalk\apivalk\Router\Route\Pagination\Paginator|null paginator()
 */
class GetUserRequest extends AbstractApivalkRequest {
    // Still empty, but now with IDE support!
}
Now, in your controller, you can type $request->body()-> and your IDE will suggest all defined properties with their correct types.

How to Run

You can trigger the generation process from your bootstrap or a CLI tool:
use apivalk\apivalk\Documentation\DocBlock\DocBlockGenerator;

$generator = new DocBlockGenerator();
$generator->run(
    '/path/to/your/api/src', 
    'App\\Api'
);

Components

  • DocBlockGenerator: The main entry point that iterates over classes.
  • DocBlockRequestGenerator: Converts an AbstractApivalkRequest into a DocBlockRequest data object.
  • DocBlockRequest: Holds the metadata for the shapes (Body, Query, Path, Sorting, Filtering).
  • DocBlockShape: Generates the PHP code for the Shape classes.
  • DocBlockResourceGenerator / DocBlockResource: Generates @property annotations for AbstractResource subclasses so you get IDE autocompletion on $resource->name, $resource->status, etc.
  • DocBlockResourceRequestGenerator / DocBlockResourceRequest: For each AbstractListResourceController, generates a typed per-resource list request (e.g. AnimalListRequest) with @method annotations for sorting(), filtering(), and paginator() wired to shape interfaces derived from the resource’s availableSortings() / availableFilters().

Resource DocBlock Generation

When DocBlockGenerator encounters an AbstractResourceController subclass, it produces two extra artifacts:
  1. Resource @property docblock — written once per resource class so that $animal->name, $animal->type, etc. autocomplete in your IDE.
  2. Per-resource list request — for each AbstractListResourceController, a typed request class (e.g. Api/v1/Animal/Request/AnimalListRequest.php) with @method annotations pointing at generated sorting/filtering shape interfaces. If the file already exists, only the docblock is updated — your class body is preserved.
This gives you full IDE autocompletion on $request->sorting()->status, $request->filtering()->createdAt, and $request->paginator() without writing the boilerplate yourself.