#scrambledrop: Scramble 0.12.23
July 2, 2025
Paginated results inference, improved documentation of authorization error responses, error-tolerant validation rules evaluation, and various type inference improvements.
Hey Laravel community!
Since the last blog post about 0.12.14 updates, there have been a lot of awesome changes in Scramble that make it smarter. In this post I’ll cover the most prominent ones.
Scramble is a Laravel API documentation generator that creates docs without requiring PHPDoc annotations: https://scramble.dedoc.co/introduction.
Paginated results inference
Previously, when using paginated responses, you had to manually annotate them for Scramble to document them correctly. Now, Scramble will automatically document paginated responses without manual annotation. This is done by inferring the type of paginators returned by the *paginate
family of methods.
/** * List available todo items. * * @response AnonymousResourceCollection<LengthAwarePaginator<TodoItemResource>> */public function index(){ return TodoItemResource::collection(TodoItem::paginate());}
This is especially useful when you include additional data alongside the paginated collection. Previously, it was difficult — or even impossible — to document both correctly due to annotation limitations.
namespace App\Http\Controllers;
use App\Models\User;use App\Http\Resources\UserResource;
class UsersController{ public function index() { $users = User::query()->paginate();
return UserResource::collection($users)->additional([ /** The total count of users */ 'count' => (int) $users->count(), ]); }}
Authorization documentation improvements
Now Scramble recognizes possible 403 (authorization error) responses in more cases.
When you call Gate::authorize
, Scramble will automatically document a 403 response:
public function store(Request $request){ Gate::authorize('create', User::class);
$data = $request->validate([ 'name' => ['required', 'string'], 'email' => ['required', 'email'], ]);
return new UserResource(User::create($data));}
Also, when you use the middleware created by Authorize::using
, Scramble will properly document the possible 403 response:
class CreateUserController extends Controller implements HasMiddleware{ public static function middleware(): array { return [ Authorize::using('create', User::class) ]; }
public function store(Request $request) { $data = $request->validate([ 'name' => ['required', 'string'], 'email' => ['required', 'email'], ]);
return new UserResource(User::create($data)); }}
Thanks to @olivernybroe and @chrisvanlier2005 for these improvements.
Error-tolerant rules evaluation
Previously, when Scramble evaluated validation rules (to document request parameters), it could fail due to code that couldn’t be evaluated.
For example, in your update
controller method, you might have used data from a real model that exists in the database:
public function update(Request $request, User $user){ $data = $request->validate([ 'level' => ['required', 'integer', Rule::in($user->account->getAvailableLevels())], ]);}
Scramble evaluated such validation rules without sending a real request. So, during documentation generation, it didn’t have access to a “correct” $user
model (and what does “correct” even mean without an actual request?). As a result, documentation generation failed in such cases.
The new release introduces error-tolerant validation rules evaluation. In the example above, Scramble will no longer fail 🚀 This is achieved by evaluating each expression one by one. Scramble processes rules individually, and if it encounters an error — such as with Rule::in($user->account->getAvailableLevels())
— it will simply ignore that rule instead of failing the entire request documentation.
This resolves many cases where requests weren’t documented. Woohoo! 🎉
Analyzing deeper 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
- Fixed document level tags ordering when using
weight
argument on#[Group]
attribute by @romalytvynenko in https://github.com/dedoc/scramble/pull/870 - Fix
setOperationId
called in an operation transformer not working by @romalytvynenko in https://github.com/dedoc/scramble/pull/872 - Fixed incorrect generic creation when looking for JSON resource in anonymous resource collection by @romalytvynenko in https://github.com/dedoc/scramble/pull/862
- Fixed memory leak when running tests if there are extensions registered via programmatic API by @romalytvynenko in https://github.com/dedoc/scramble/pull/864
- Allow using
#[Group]
attribute on route’s controller methods by @romalytvynenko in https://github.com/dedoc/scramble/pull/865 - Fixed
bool
typehint onauthorize
prevented Scramble into properly inferring 403 response absence by @romalytvynenko in https://github.com/dedoc/scramble/pull/857 - Add support for inferring a type on property fetch or method call on an argument by @romalytvynenko in https://github.com/dedoc/scramble/pull/858
- Fixed fully qualified names resolution of methods defined in traits by @romalytvynenko in https://github.com/dedoc/scramble/pull/860
- Improve
ExportDocumentation
command by @lucascbittencourt in https://github.com/dedoc/scramble/pull/800 - Improved
204
response handling, fixed parameter types templates by @romalytvynenko in https://github.com/dedoc/scramble/pull/801 - Fixed
uuid
model key compatibility with Laravel 12.x by @sbbjss in https://github.com/dedoc/scramble/pull/785 - Fixed
#[BodyParameter]
attribute not adding the information to the parameter by @romalytvynenko in https://github.com/dedoc/scramble/pull/781 - Added configurable layout option for Spotlight Elements UI by @superdejooo in https://github.com/dedoc/scramble/pull/787
- Fixed scrollbar color in dark color scheme by @romalytvynenko in https://github.com/dedoc/scramble/pull/790
- Analyzing methods called in controller methods by @romalytvynenko in https://github.com/dedoc/scramble/pull/793
- @superdejooo made their first contribution in https://github.com/dedoc/scramble/pull/787
- Improved validation rules evaluation to be more tolerant by @romalytvynenko in https://github.com/dedoc/scramble/pull/809
- Add
sometimes
validation rule support by @SocolaDaiCa in https://github.com/dedoc/scramble/pull/802 - Fix authorization when using Authorize middleware by @olivernybroe in https://github.com/dedoc/scramble/pull/820
- Make logo optional to prevent broken image by @vinkla in https://github.com/dedoc/scramble/pull/821
- Extend inference API: added the ability to hook in into any method call, including cases when the object a method being called on is unknown by @romalytvynenko in https://github.com/dedoc/scramble/pull/822
- Remove “dependencies” concept from reference types by @romalytvynenko in https://github.com/dedoc/scramble/pull/823
- Pagination inference by @romalytvynenko in https://github.com/dedoc/scramble/pull/826
- Added ability to leave comment to array items in properties defaults by @romalytvynenko in https://github.com/dedoc/scramble/pull/827
- Add
AuthorizationException
whenGate::authorize
is called by @chrisvanlier2005 in https://github.com/dedoc/scramble/pull/828 - Allow type inference for
@property-read
in JsonResource by @chrisvanlier2005 in https://github.com/dedoc/scramble/pull/830 - String literals decalred with var should be represented as enums not examples by @romalytvynenko in https://github.com/dedoc/scramble/pull/843
- Save tags to the OpenAPI document’s tags list by @romalytvynenko in https://github.com/dedoc/scramble/pull/845
- Make sure not to keep schemas extracted from request method calls if parameters are not used by @romalytvynenko in https://github.com/dedoc/scramble/pull/846
- Fixed accidental closures evaluation when evaluating rules containing closures (like
Rule::prohibitedIf
) by @romalytvynenko in https://github.com/dedoc/scramble/pull/847 - Added support for manual documentation on parameters with names defined as class’ consts by @romalytvynenko in https://github.com/dedoc/scramble/pull/848
- Added type inference for binary operators that return boolean by @romalytvynenko in https://github.com/dedoc/scramble/pull/849
- Fix error when configuring OpenAPI docs using a callback with DocumentTransformers parameter by @d3radicated in https://github.com/dedoc/scramble/pull/853
Thanks!
Try out Scramble 0.12.23 and let me know what you think! Thanks for checking this post out. If you have any questions, ideas, suggestions, feel free to drop me a line to roman@dedoc.co