Scramble 0.11.0 is here! Laravel Data support, schema enforcement and more
Learn more

Requests

Are you a visual learner?
Get most out of Scramble with in-depth screencasts.

Scramble documents request part of endpoints by automatically extracting route parameters and generating parameter types and descriptions based on route model binding. Query parameters or request body parameters are documented based on validation rules.

Path params

Scramble identifies and documents all route path parameters automatically. For example:

routes/api.php
Route::put('/todo-items/{id}', [TodoItemsController::class, 'update']);
// app/Http/Api/Controllers/TodoItemsController.php
class TodoItemsController
{
public function update(Request $request, int $id) {/* ... */}
}

In this example, the {id} path parameter is documented without any additional setup. Scramble generates default documentation, including the parameter type.

If the parameter is implicitly (or explicitly) bound to a model, Scramble determines the parameter type based on the model’s route key.

int key: The parameter type will be integer. UUID key: The parameter type will be string, with uuid format.

For example:

routes/api.php
Route::put('/todo-items/{todoItem}', [TodoItemsController::class, 'update']);
// app/Http/Api/Controllers/TodoItemsController.php
class TodoItemsController
{
public function update(Request $request, TodoItem $todoItem) {/* ... */}
}

In this case assuming the TodoItem model uses an integer key, Scramble will document the {todoItem} parameter as an integer with the default description "The todo item ID.".

Scramble supports custom route keys. If you override the getRouteKeyName method in your model, Scramble will document the parameter type based on the type of the property specified in that method.

You can enhance or override the default documentation by adding PHPDoc to the corresponding controller method parameters. For example:

use App\Models\TodoItem;
class TodoItemsController
{
/**
* Update the specified todo item.
*
* @param string $todoItem The todo item being updated.
*/
public function update(Request $request, TodoItem $todoItem) {/*...*/}
}

Here:

  • Scramble will use the custom type (string) and description (“The todo item being updated”) from the PHPDoc.
  • This overrides the default parameter type and description generated by Scramble.

Explicit binding and parameter matching caveats

Laravel allows you to explicitly define how route parameters are resolved to models using the Route::bind method. For example:

Route::bind('any_user', function (string $value) {
return User::where('name', $value)->firstOrFail();
});

Here’s a route and controller that utilize this binding:

routes/api.php
Route::get('/users/{any_user}', UserController::class);
// app/Http/Controllers/UserController.php
class UserController
{
/**
* @param User $user The resolved user instance.
*/
public function __invoke(Request $request, User $user)
{
// $user is the resolved model instance
}
}

When the {any_user} parameter is used in the route, Laravel resolves it to a User instance using the custom binding. This instance is then passed to the controller method as the $user parameter. Laravel recognizes the parameter type (User) and ensures it is provided from the route parameters instead of resolving it from the service container.

In this scenario, Scramble cannot automatically associate the {any_user} route parameter with the $user argument in the controller. As a result, the $user parameter’s PHPDoc documentation will not appear correctly in the generated API documentation.

To address this issue, you need to explicitly add a return type to the closure provided to the Route::bind method:

Route::bind('any_user', function (string $value): User {
return User::where('name', $value)->firstOrFail();
});

Adding the return type (User) helps Scramble correctly identify that {any_user} resolves to a User instance. This ensures the parameter is correctly mapped in the API documentation, and the $user argument in your controller is documented as expected.

Body

Request body documentation is generated based on using request validation rules and attributes retrieval (methods calls) on request object.

When request HTTP method is GET, DELETE, or HEAD parameters are documented as a part of a query string. For other HTTP methods, parameters are documented as requests body.

Validation rules

Currently, there are 3 ways of validating requests that are understood by Scramble:

  • Call to validate on $request or $this in controller’s method
  • Call to Validator facade’s make method with method call on request ($request->?()) as a first argument
  • rules method on custom FormRequest class
use App\Models\TodoItem;
class TodoItemsController
{
public function update(Request $request, TodoItem $item)
{
$request->validate([
'body' => ['required', 'string'],
'is_complete' => 'bool',
]);
}
}

Based on these validation rules Scramble knows that there are 2 request body params: body and is_complete. Same applies to Validator::make call.

use App\Models\TodoItem;
use Illuminate\Support\Facades\Validator;
class TodoItemsController
{
public function update(Request $request, TodoItem $item)
{
Validator::make($request->all(), [
'body' => ['required', 'string'],
'is_complete' => 'bool',
]);
// ...
}
}

The same applies to the rules method in custom FormRequest.

When you need to mark a parameter as a part of query string for non-GET requests, you can use @query PHPDoc annotation:

$request->validate([
/** @query */
'per_page' => ['required', 'integer'],
]);

Documenting request params manually

You can add docs to your request params by adding PHPDoc block near a validation rules of the param:

use App\Models\Location;
class LocationsController
{
public function update(Request $request, Location $location)
{
$request->validate([
/**
* The location coordinates.
* @var array{lat: float, long: float}
* @example {"lat": 50.450001, "long": 30.523333}
*/
'coordinates' => 'array',
]);
}
}

@example should be either a string, or valid JSON.

You can use @var to re-define or clarify type inferred from validation rules. Manually defined type will always take precedence over the automatically inferred type.

A simple PHP comment before a param will also be used as a request body parameter description:

use App\Models\TodoItem;
class TodoItemsController
{
public function update(Request $request, TodoItem $item)
{
$request->validate([
// Whether the task is complete.
'is_complete' => 'bool',
]);
}
}

Ignoring params

If you need to avoid a parameter being added to documentation, you can mark it with @ignoreParam PHPDoc annotation. In the following example id parameter won’t be documented.

use App\Models\TodoItem;
class TodoItemsController
{
public function index(Request $request)
{
$request->validate([
/** @ignoreParam */
'id' => 'integer',
]);
// ...
}
}

Rules evaluation caveats

It is important to keep in mind that rules are evaluated to be analyzed: rules method is called when there is a custom request class and the array with rules passed to the validate is evaluated as well.

This adds not obvious benefits to the resulting documentation when Rule::in validation rule is being represented as enum with all possible values in the docs.

But also it requires a developer to write rules in certain way when using validation via validate method call in controller. Only these expressions can be evaluated correctly:

  • Using variables passed to the controller
  • Static calls to classes
  • Using global functions (app())

Declaring local variable in method before calling validate and using it there will cause an error.

Supported rules

  • required
  • string
  • bool, boolean
  • number
  • int, integer
  • array
  • in, Rule::in
  • nullable
  • email
  • uuid
  • exists (marks value as int if attribute name is either id or *_id)
  • min (numeric types only)
  • max (numeric types only)
  • Enum
  • confirmed

Method calls on a request object

When you manually retrieve attributes from a request object, Scramble will automatically document them as part of the request.

For example, if we want to get a paginated list of to-do items, a user can pass an integer per_page as a request parameter:

use App\Models\TodoItem;
use Illuminate\Support\Facades\Validator;
use Illuminate\Http\Request;
class TodoItemsController
{
public function index(Request $request)
{
$items = TodoItem::query()
->paginate($request->integer('per_page', 15));
// ...
}
}

Scramble will add per_page to the API documentation as integer type and will document that 15 is a default value.

These Request methods are supported:

  • integer
  • float
  • boolean
  • enum
  • query - Scramble will mark a parameter as a part of query string for non-GET requests
  • string, str, get, input, post

You can add description, example, default value for parameters manually when needed. Using @query annotation, you can mark the parameter as a part of query string for non-GET requests.

/**
* Amount of items per page.
* @example 50
* @default 15
*/
$perPage = $request->integer('per_page') ?: 15;

When you want to avoid adding attributes to API documentation, use @ignoreParam PHPDoc attribute. In this case foo attribute will not be documented.

/** @ignoreParam */
$data = $request->get('foo');

Adding title and description

Scramble can get endpoint docs from PHPDoc comment of the route’s method.

summary is the first row of the doc. description is the other text in doc. When there is only one line of text in PHPDoc it is treated as summary, as you can expect.

/**
* This is summary.
*
* This is a description. In can be as large as needed and contain `markdown`.
*/

Organizing in folders

All the endpoints are organized in folders by controller name. Endpoint organization in rendered docs is based on OpenAPI operation’s tags.

When there are a lot of controllers in your application, you will have a ton of folders, and it may be hard to navigate through that list of folders.

You can add your own tags on the controller’s level using @tags in PHPDoc. This will put all the routes from that controller in this folder. It allows you to reduce the amount of folders in rendered docs and organize the docs in a way that makes more sense.

Multiple tags are supported: simply write them in one line separated via comma.

Please note that the UI Scramble uses for rendering docs doesn’t support nested folders. It uses the first tag as a folder. Other tags will still be there in OpenAPI documentation but won’t be shown in the UI.

/**
* @tags Media
*/
class DownloadMediaController
{
public function show(Media $mediaItem)
{
return $mediaItem;
}
}

Operation ID

Scramble generates unique operation ID for your endpoints. It is based on the route name. If route name is not unique, Scramble will use controller and method name and will create a unique ID based on that.

You always can override operation ID by adding @operationId to the route’s method PHPDoc.

class DownloadMediaController
{
/**
* @operationId getMediaItem
*/
public function show(Media $mediaItem)
{
return $mediaItem;
}
}

Request media type

By default, Scramble specifies application/json as request media type (Content-Type header). When some field in validation rules has file rule, Scramble will use multipart/form-data.

You always can override request media type by adding @requestMediaType to the route’s method PHPDoc.

class UploadMediaController
{
/**
* @requestMediaType multipart/form-data
*/
public function show(Request $request)
{
// ...
}
}
Scramble PRO
Comprehensive API documentation generation for Spatie’s Laravel Data and Laravel Query Builder.