Laravel
Collections
PHP autodoc-laravel tracks the item and key types of Laravel collections.
Collection analysis works the same whether the collection comes from a collect([...]) call or from an Eloquent query like Planet::all() or ->get().
Example
$planets = Planet::all();
return response()->json([
'names' => $planets->pluck('name'),
'total' => $planets->count(),
'first' => $planets->first(),
]);
The documented response resolves each collection method against the model's column types:
{
names: string[]
total: number
first: {
id: number
name: string
// ... other Planet columns
} | null
}
Supported methods
These Collection methods are currently recognized:
avg, average, contains, count, each, filter, first, flatten, get, groupBy, implode, isEmpty, isNotEmpty, keyBy, last, map, mapWithKeys, pluck, reject, reverse, skip, slice, sortBy, sortByDesc, sortDesc, sum, take, toArray, unique, values
How these methods affect types:
first,lastandgetreturn the collection item type. When you pass a default value, its type is included in the result; without one,nullis.pluckresolves the plucked property's type from the item shape, including keyed plucks likepluck('name', 'id').- Scalar methods have fixed return types matching Laravel's runtime behavior:
sumis a number,counta non-negative integer,avg/averagea number or null,isEmpty/isNotEmpty/containsa boolean,implodea string. - Methods like
filter,sortBy,unique,reverse,takeandskippass the collection shape through unchanged.valuesdrops the keys,toArrayconverts to a plain array.
Unrecognized methods fall back to regular code analysis, so custom collection classes and macros may still resolve through their own return types.
Analyzed callbacks
Callbacks passed to map, mapWithKeys and each are analyzed - both closures and arrow functions - so the resulting item shape comes from your actual callback code:
$planets = Planet::all();
return response()->json(
$planets->map(fn ($planet) => [
'id' => $planet->id,
'label' => $planet->name,
])
);
{
id: number
label: string
}[]
Mutating models inside each()
each() returns the collection itself, but its callback is still analyzed. Attributes set on the callback parameter - for example with setAttribute - are merged into the collection's item type:
$planets = Planet::all();
$planets->each(function ($planet) {
$planet->setAttribute('flag', true);
});
return $planets;
The documented response items contain all Planet columns plus flag: boolean. This works for a value-less $planets->each(...); statement as well, and attributes set conditionally inside the callback become optional fields.