Releases
Documenting query builders defined in called methods
Let’s say you have the following controller that retrieves a list of hotels and returns this list in a response:
class HotelsController
{
public function __construct(public HotelsListService $hotelsListService) {}
public function index()
{
$hotels = $this->hotelsListService->list($request->int('per_page', 15));
return HotelResource::collection()
}
}
And the following HotelsListService
implementation:
class HotelsListService
{
public function list(int $perPage): QueryBuilder
{
return QueryBuilder::for(Hotel::class)
->allowedFilters([
'rooms',
'name',
'price',
])
->allowedSorts([
'price',
'rooms',
]);
}
}
Prior to this version Scramble documented only query builders that were constructed in the controller method’s body. But now Scramble analyzes all method calls in the controller’s method so now it can document such cases!
What’s Changed
- Looking for query builder definitions in the called methods
Analyzing calls in controller methods
Ugh, this was a hard one.
Imagine you have the following controller:
class ItemsController
{
public function __construct(private ItemsRetrievalService $listService) {}
public function __invoke(Request $request)
{
$this->listService->ensureCanList();
return ItemResource::collection($this->listService->get());
}
}
And the following service class:
class ItemsRetrievalService
{
/**
* @throws AuthorizationException
*/
public function ensureCanList()
{
// ...
}
// ...
}
You can see that the ensureCanList
method is marked with a @throws
AuthorizationException
annotation in the PHPDoc. Prior to this update, Scramble did not document such code as potentially producing a 403
response. This was due to how Scramble analyzed the code: it minimized how much source code it parsed into an AST and how much of that AST it traversed. Since ensureCanList
’s return type wasn’t used in the controller method’s return type, Scramble never even looked at it.
Starting from version 0.12.17
, Scramble analyzes all methods called within controller methods! It still prioritizes performance — it reads only the PHPDoc and skips parsing and traversing the AST if the method’s return type isn’t used in the response.
This means you can now document exceptions using the @throws
annotation, and if such a method is called in a controller, Scramble will correctly recognize and document the possible error response.
It might seem like a “nice-to-have” feature, but this update is a stepping stone toward improved type inference in Scramble. Imagine support for things like collect()->map()
and beyond — can’t wait to make that happen. Stay tuned!
What’s Changed
- Added configurable layout option for Spotlight Elements UI by @superdejooo in #787
- Fixed scrollbar color in dark color scheme by @romalytvynenko in #790
- Analyzing methods called in controller methods by @romalytvynenko in #793
New Contributors
- @superdejooo made their first contribution in #787
What’s Changed
- Fixed
#[BodyParameter]
attribute not adding the information to the parameter by @romalytvynenko in #781
Enum cases description
This version adds support for enum case descriptions — a long-requested and highly upvoted feature!
Now, you can add PHPDoc comments above enum cases, and Scramble will use them as enum descriptions:
enum JobStatus: string
{
/**
* When the job application is available.
*/
case OPEN = 'open';
/**
* When the job has been closed.
*/
case CLOSED = 'closed';
}
This will produce the following JSON schema:
{
"title": "JobStatus",
"type": "string",
"enum": ["open", "closed"],
"description": "|---|---|\n|`open`|When the job application is available.|\n..."
}
If you use OpenAPI rendering solutions that support it, you can use the x-enumDescriptions
extension for case descriptions by setting scramble.enum_cases_description_strategy
to extension
. In this case, the generated JSON schema will look like this:
{
"title": "JobStatus",
"type": "string",
"enum": ["open", "closed"],
"x-enumDescriptions": {
"open": "When the job application is available.",
"closed": "When the job has been closed."
}
}
Woohoo!
What’s Changed
What’s Changed
- Added
toJson
,toArray
, andtoResponse
methods support on data objects
What’s Changed
- Fix model name detection on linebreak crlf by @canyoningdb in #771
- Added ability to specify the types accepted by specific type by @romalytvynenko in #775
- Prevent leaking comments from service classes into docs by @romalytvynenko in #776
New Contributors
- @canyoningdb made their first contribution in #771
This release adds complete only
and except
support on Laravel Data objects. This includes conditional only
and except
as well as support for onlyProperties
and exceptProperties
methods defined in data objects classes.
Consider the following example:
public function show(Company $company)
{
return CompanyData::from($company)->only('id');
}
Now, Scramble will correctly document that this endpoint returns a structure containing only id
property:
{
"type": "object",
"properties": {
"id": {
"type": "integer"
}
},
"required": [
"id"
]
}
What’s Changed
- Added
only
andexcept
support on Laravel Data objects
This is a relatively small release, but brings support for long awaited array’s in request root and some inference improvements.
Support for arrays in request body root
Now it it possible to provide validation rules for arrays as request body root:
$request->validate([
'*.foo' => ['required', 'string'],
'*.bar' => ['required', 'string'],
]);
Scramble will correctly recognize that request body is an array of objects with foo
and bar
properties.
Type inference improvements
Now Scramble will be able to infer types originating from typed property calls. This allows you to have a correct documentation for method calls on services you inject into your controller.
// CompanyController.php
<?php
namespace App\Http\Controllers\Api;
use App\CompanyDataFactory;
use App\Http\Controllers\Controller;
use App\Models\Company;
class CompanyController extends Controller
{
public function __construct(
private readonly CompanyDataFactory $companyDataFactory,
) {}
/**
* Get company.
*/
public function show(Company $company)
{
return $this->companyDataFactory->createTerseCompanyData($company);
}
}
// CompanyDataFactory.php
<?php
namespace App;
use App\Data\CompanyData;
class CompanyDataFactory
{
public function createTerseCompanyData($model): CompanyData
{
return CompanyData::from($model)->only('id');
}
}
Scramble will correctly document the response from show
controller’s method 🔥
What’s Changed
What’s Changed
- Fixed breaking change in Laravel Data 4.14 (attributes class was changed)
What’s Changed
- Added option to hide schemas in the navigation by @ferdinandfrank in #747
- Fixed missing
required
info whenrequired
was used withenum
validation rule by @romalytvynenko in #758 - Added support of
date_format
rule by @YournameITManoah in #748 - Fixed handling of methods with different casing and missing methods by @romalytvynenko in #763
New Contributors
- @YournameITManoah made their first contribution in #748
What’s Changed
- Added Laravel 12.x compatibility
What’s Changed
- Fixed filter parameters becoming nested if dot used in a name
What’s Changed
- Improved exception message when normalizing data type
What’s Changed
- Fix constructor called methods side effects overwriting the type by @romalytvynenko in #740
What’s Changed
- Fix arrays unpacking in arrays passed to
->allow*(...)
methods of query builder