skip to content

Request Data & Replies

The Request and Response objects a Laravel handler uses: input, uploads, the session, views, JSON, redirects, streams and API resources. Interviewers use them to check everyday handler fluency.

on this pageshow

explore

questions

page 1 of 2

In Laravel, what is an API resource class such as a JsonResource, and why return one instead of the Eloquent model itself?

level: juniorimportance: must knowfreq 62%

answer

  1. a transformation layer between model and JSON
  2. php artisan make:resource WorkoutResource
  3. toArray(Request $request) returns the shape
  4. $this proxies to the wrapped model
  5. toResource() looks in App\Http\Resources

basics

~20 s

An API resource is a class extending JsonResource whose toArray() maps one model to the exact JSON the API promises, so column renames, new columns and internal fields do not leak into responses by accident.

solid answer

~40 s

A resource is generated with `php artisan make:resource WorkoutResource` into `app/Http/Resources`, extends `Illuminate\Http\Resources\Json\JsonResource`, and returns an explicit array from `toArray(Request $request)`. Inside it, `$this->title` works because the resource forwards property reads and method calls to the wrapped model. You return it from a controller (`new WorkoutResource($workout)`, or `$workout->toResource()` in Laravel 13), and Laravel turns it into a `JsonResponse` with the outermost payload wrapped in `data`. Returning the model directly serializes whatever its own `toArray()` produces, so the response contract follows the database schema; a resource makes the contract an explicit, reviewable allow-list that can rename fields, format dates and include relations conditionally.

code

bash · 2 lines
bash
php artisan make:resource WorkoutResource
php artisan make:resource WorkoutCollection

go deeper

for a junior

Recall the command, the base class and the one method: make:resource, JsonResource, toArray(Request). Be able to return new WorkoutResource($workout) from a controller and say the output is wrapped in data.

for a middle

Explain the delegation that makes $this->column work, why the stub's parent::toArray() exposes everything, and how toResource() and #[UseResource] find the class in Laravel 13.

for a senior

Argue the contract angle: a mobile API outlives app releases, so the response shape must be an explicit allow-list that a migration cannot silently widen, with model-level hiding as a backup only.

for a principal

Frame resources as the versioned boundary of a public API: when to fork a V2 resource instead of editing one, and how to keep response shapes reviewable across many teams and endpoints.

## What an API resource is An **API resource** in Laravel is a small class that sits between an Eloquent model and the JSON your API sends back. It extends `Illuminate\Http\Resources\Json\JsonResource`, receives the model through its constructor (stored in the public `$resource` property), and implements one method, `toArray(Request $request)`, which returns the array that becomes the response body. The class also implements `Responsable`, so a controller can return it directly: the router calls its `toResponse()` method, which builds an `Illuminate\Http\JsonResponse`. A companion class, `ResourceCollection`, does the same job for a list of models. Think of a mobile fitness-tracker API. A `Workout` model has columns such as `id`, `user_id`, `type`, `distance_m`, `duration_s`, `device_serial` and `created_at`. The iOS and Android apps want `distance_km`, a human duration, and never the device serial. The resource is where that mapping lives. ## Creating and returning one 1. Generate the class: `php artisan make:resource WorkoutResource` writes `app/Http/Resources/WorkoutResource.php`. 2. Replace the generated body of `toArray()` with an explicit array. 3. Return it from the controller: `return new WorkoutResource($workout);` or, in Laravel 13, `return $workout->toResource();`. Two details of the generated file matter: - The stub's `toArray()` returns `parent::toArray($request)`, and the parent simply calls the wrapped model's own `toArray()`. **An untouched resource is therefore not a filter at all**: it outputs every attribute the model would. - Inside `toArray()`, `$this->distance_m` and `$this->user()` work because the base class uses `DelegatesToResource`, whose `__get`, `__isset` and `__call` forward to `$this->resource`. `toResource()` (and `toResourceCollection()` on collections and paginators) find the class by convention: for `App\Models\Workout` they try `App\Http\Resources\WorkoutResource`, then `App\Http\Resources\Workout`. A `#[UseResource(CustomWorkoutResource::class)]` attribute on the model overrides the guess, and passing a class name, `toResource(CustomWorkoutResource::class)`, overrides both. If nothing matches, a `LogicException` reports that no resource class was found. Laravel 13 also adds a `--json-api` flag to `make:resource` for its first-party JSON:API resources, a separate, spec-driven variant. ## Why not return the model directly Returning `$workout` from a route also produces JSON, via the model's own serialization (its `toArray()`, filtered by the model's hidden and visible lists). The difference is where the response contract is defined. | Concern | Returning the model | Returning a resource | |---|---|---| | Which fields appear | Every column and appended accessor not hidden on the model | Only the keys listed in `toArray()` | | A new column in a migration | Appears in the API on the next deploy | Invisible until someone adds it to the resource | | Renaming or formatting | Needs accessors on the model, affecting every use | Done per API shape, model untouched | | Conditional fields and relations | Not expressible per request | `when()`, `whenLoaded()`, `whenCounted()` | | Top-level wrapper and meta | None; bare object or paginator array | `data` wrapper, `with()`, `additional()`, pagination `links` and `meta` | For a public mobile API this is decisive: shipped app versions cannot be updated instantly, so the JSON shape is a contract, and a contract should be an explicit **allow-list** reviewed in one file rather than a side effect of the table schema. Hiding sensitive attributes on the model is a second, model-wide safety net; it is not a substitute for choosing what each endpoint exposes. Resources also keep presentation choices, such as ISO 8601 dates, rounded units and renamed keys, out of the model, so a web page, a queued export and the mobile API can each present the same model differently. ## A minimal example ```php <?php namespace App\Http\Resources; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; class WorkoutResource extends JsonResource { public function toArray(Request $request): array { return [ 'id' => $this->id, 'type' => $this->type, 'distance_km' => round($this->distance_m / 1000, 2), 'duration_s' => $this->duration_s, 'started_at' => $this->created_at?->toIso8601String(), ]; } } ``` The `device_serial` and `user_id` columns never reach the client, the unit conversion lives in one place, and the model stays free of API-specific accessors. ## Common traps - **Leaving the stub untouched** and believing the resource hides anything; it returns the model's full array. - **Reading relations directly** (`$this->user->name`) inside a resource used for a list, which lazy-loads one query per item; use `whenLoaded()` and eager-load in the controller. - **Calling `->toArray()` on the resource yourself** and returning that array, which skips the wrapper, `with()`, `additional()` and status handling that `toResponse()` provides. - **Assuming the resource changes persistence**: it is output only. Saving, mass assignment and validation happen elsewhere.

  • What does the toArray() in a freshly generated make:resource stub return?
    It returns `parent::toArray($request)`, and `JsonResource::toArray()` returns the wrapped model's own `toArray()` (or the array itself if you wrapped an array, or `[]` for null). So an untouched resource outputs every visible attribute and appended accessor of the model; it only becomes an allow-list once you replace that line with explicit keys.
  • How does $this->distance_m resolve inside a resource that declares no such property?
    `JsonResource` uses the `DelegatesToResource` trait. Its `__get` reads `$this->resource->{$key}`, `__isset` checks the same, and `__call` forwards method calls (after checking resource macros) to the wrapped model. Array access is forwarded too, so a resource wrapping an array also works with `$this['key']`.
  • What happens when $workout->toResource() cannot find a matching class?
    It first honours a `#[UseResource]` attribute on the model, then tries `App\Http\Resources\WorkoutResource` and `App\Http\Resources\Workout`. If none of those classes exists it throws a `LogicException` saying it failed to find a resource class for the model. It never generates a class on the fly; pass a class name to `toResource()` or add the attribute.

saying these in an interview costs you the question

  • The make:resource stub already exposes only safe, whitelisted fields.
  • A resource changes how the model is stored or validated.
  • $this->title fails inside a resource because JsonResource has no title property.
  • Returning the model is just as safe, because new columns never reach the JSON.
  • toResource() generates a resource class at runtime when none exists.
  • Resources are only for collections; single models should be returned bare.
open as a page

In a Laravel controller, how do $request->input(), query(), all(), only() and except() differ when reading a search form?

level: juniorimportance: must knowfreq 72%

basics

~20 s

input() reads a field from the request body and query string together (body wins on a clash) and follows dot paths; query() reads only the query string; all() returns every field plus uploaded files; only() and except() return a filtered subset.

open as a page

In Laravel, how do redirect()->to(), redirect()->route(), to_route(), back() and redirect()->away() differ, and which status do they send?

level: juniorimportance: must knowfreq 60%

basics

~20 s

All five return an Illuminate\Http\RedirectResponse with status 302 unless you pass another code. to() takes a path or URL, route() and to_route() a route name, back() the previous page, and away() an external URL used as-is.

open as a page

In a Laravel route or controller, what response does the framework build when you return a string, an array, an Eloquent model or a view?

level: juniorimportance: must knowfreq 62%

basics

~20 s

Laravel's router wraps the return value: a string or view becomes an HTML response with status 200, while arrays, Eloquent models and collections become a JsonResponse. A model created during the request returns 201 instead of 200.

open as a page

In Laravel, how do you store, read and remove session data with get(), put(), push(), pull() and forget()?

level: juniorimportance: must knowfreq 66%

basics

~20 s

Through $request->session(), the session() helper or the Session facade: put() stores a value, get() reads it with an optional default, push() appends to an array value, pull() reads and removes in one call, and forget() deletes keys; flush() empties the session.

open as a page

In a Laravel controller, how do you read an uploaded profile photo and save it to a disk with store()?

level: juniorimportance: must knowfreq 68%

basics

~10 s

$request->file('photo') returns an Illuminate\Http\UploadedFile; calling ->store('avatars') writes it to the default disk under a random 40-character name with a content-based extension and returns the relative path, or false if the write fails.

open as a page

In a Laravel API resource, what do whenLoaded() and whenCounted() do, and why use them instead of reading the relation directly?

level: middleimportance: must knowfreq 55%

basics

~10 s

whenLoaded('exercises') includes a relation only if it was already eager-loaded, and whenCounted('exercises') includes exercises_count only if withCount or loadCount set it; otherwise the key is dropped and no query runs.

open as a page

In Laravel, how do $request->has(), filled() and missing() differ for a search field submitted empty or not at all?

level: middleimportance: must knowfreq 58%

basics

~20 s

has() is true when the key is present, even with an empty value; filled() also requires a non-blank value; missing() means the key is absent. A blank text field is present but not filled; an unchecked checkbox is missing.

open as a page

In Laravel, how does redirect()->intended() send a bookshop customer back to the checkout page after login, and where does url.intended come from?

level: middleimportance: must knowfreq 55%

basics

~20 s

When a guest hits a protected page, the exception handler calls redirect()->guest() to the login route, which stores the current URL as url.intended in the session. After login, redirect()->intended($default) pulls that key and redirects there, or to $default.

open as a page

In Laravel, how long does session flash data live, and what do reflash(), keep() and now() change about it?

level: middleimportance: must knowfreq 52%

basics

~20 s

flash() data is readable for the rest of the current request and during the next one, then deleted. reflash() extends all of it by one request, keep() does so for named keys, and now() stores a value for this request only.

open as a page

In Laravel, how do you use response()->streamDownload() to export a million-row sales report as CSV without building it in memory?

level: middleimportance: must knowfreq 42%

basics

~20 s

response()->streamDownload($callback, 'sales.csv') returns a StreamedResponse with an attachment Content-Disposition. Its callback runs while the response is sent, writing rows with fputcsv to php://output from a lazy() or cursor() query, so no full file or array is ever held.

open as a page

In Laravel's UploadedFile, why prefer hashName() and extension() over getClientOriginalName() and clientExtension() when saving a photo?

level: middleimportance: must knowfreq 55%

basics

~20 s

getClientOriginalName(), getClientOriginalExtension() and clientExtension() come from what the client sent and can be forged; hashName() is a random 40-character name and extension() is guessed from the file's actual contents, so they reflect the server's view, not the client's claim.

open as a page

In Laravel, what changes when response()->stream() receives a generator closure instead of a plain closure that echoes output?

level: juniorimportance: should knowfreq 28%

basics

~20 s

Both return a Symfony StreamedResponse. With a generator, Laravel echoes each yielded chunk, flushes PHP's output buffer after it and adds X-Accel-Buffering: no; with a plain closure nothing is flushed or added unless you do it yourself.

open as a page

In Laravel, when do you write a ResourceCollection class instead of calling WorkoutResource::collection(), and how do with() and additional() add top-level meta?

level: middleimportance: should knowfreq 36%

basics

~20 s

WorkoutResource::collection() builds an anonymous collection that maps each item and is enough for plain lists and pages. Write a ResourceCollection when the list itself needs fields, meta or pagination hooks; with() adds class-defined meta, additional() adds per-call meta.

open as a page

In a Laravel API resource, how do when() and mergeWhen() include fields only for some viewers, and what removes the key otherwise?

level: middleimportance: should knowfreq 42%

basics

~10 s

when($condition, $value) returns the value when the condition is true and a MissingValue otherwise; mergeWhen($condition, [...]) does the same for several keys. Laravel strips every MissingValue before encoding, so the keys vanish.

open as a page

In Laravel, how do $request->flash(), flashOnly(), flashExcept() and the old() helper repopulate a form on the next request?

level: middleimportance: should knowfreq 50%

basics

~20 s

flash() copies the current request's input into the session as old input for the next request only; flashOnly() and flashExcept() filter what is copied. On that next request, old('field', $default) reads it back, typically inside a Blade value attribute.

open as a page

In Laravel, what is the difference between $request->merge() and mergeIfMissing(), and why can mergeIfMissing() leave a blank field unset?

level: middleimportance: should knowfreq 34%

basics

~10 s

merge() writes keys into the request's input, overwriting existing values; mergeIfMissing() writes only keys that are absent. A field submitted blank is present as null, so mergeIfMissing() does not replace it with the default.

open as a page

In Laravel, what do $request->boolean(), integer(), date() and enum() return when a field is missing, empty or malformed?

level: middleimportance: should knowfreq 42%

basics

~20 s

boolean() is true only for 1, true, on and yes; integer() is an (int) cast, so bad text gives 0; date() returns null when empty but throws on bad input; enum() returns the default for empty or unknown values.

open as a page

In Laravel, why do redirects after a POST default to 302, when would you send 303 instead, and how do you do it?

level: middleimportance: should knowfreq 32%

basics

~20 s

Laravel's redirect builders default to 302. Browsers turn a 302 after a form POST into a GET, so it works for HTML forms, but only 303 guarantees a GET for any method; pass it as the status argument.

open as a page

On a Laravel RedirectResponse, what do with(), withInput() and withErrors() each put in the session for the next request?

level: middleimportance: should knowfreq 50%

basics

~10 s

with() flashes any key and value, withInput() flashes the request input under _old_input without uploaded files, and withErrors() flashes a MessageBag into the errors ViewErrorBag. All three survive only the next request.

open as a page

In Laravel, how do you set a cookie with response()->cookie() or withCookie() versus Cookie::queue(), and when do you need each?

level: middleimportance: should knowfreq 42%

basics

~20 s

Chain ->cookie() or ->withCookie() when you hold the response object. Use Cookie::queue() when the code setting the cookie runs before the response exists; the web group's AddQueuedCookiesToResponse middleware adds queued cookies to whatever response comes back.

open as a page

In Laravel, how do response()->download() and response()->file() differ when a concert-venue app serves a PDF ticket?

level: middleimportance: should knowfreq 40%

basics

~20 s

Both return a Symfony BinaryFileResponse for a file on the server's disk. download() adds Content-Disposition: attachment with a chosen filename, so the browser saves it; file() adds no disposition, so the browser displays the PDF inline.

open as a page

In Laravel, when do you use response()->json() instead of returning an array, and what do its status, headers and options arguments control?

level: middleimportance: should knowfreq 45%

basics

~10 s

Returning an array gives JSON with status 200 and nothing else. response()->json($data, $status, $headers, $options) adds a chosen status, extra headers and json_encode flags, and returns an Illuminate\Http\JsonResponse you can keep chaining.

open as a page

In Laravel 13, what does SESSION_DRIVER default to, and how do the database, file, cookie, redis and array drivers differ?

level: middleimportance: should knowfreq 48%

basics

~20 s

Laravel 13's skeleton sets SESSION_DRIVER=database, storing sessions in a sessions table that its first migration creates. file suits one server, cookie keeps the whole payload in an encrypted cookie, redis and memcached are shared fast stores, and array persists nothing.

open as a page

In Laravel, how does response()->eventStream() send a live progress feed, and what are StreamedEvent and the </stream> end marker for?

level: middleimportance: should knowfreq 30%

basics

~10 s

response()->eventStream() writes each value a generator yields as a server-sent event named update, JSON-encoding arrays. A yielded StreamedEvent sets the event name, and a final </stream> message tells the client the stream ended.

open as a page

In Laravel, what is the difference between $request->hasFile('photo') and $request->file('photo')->isValid() for an upload?

level: middleimportance: should knowfreq 40%

basics

~20 s

hasFile() asks whether the request holds a file object with a real temporary path; isValid() asks whether that particular upload finished with no error and came through PHP's upload mechanism. For multiple files, hasFile() is true if any one qualifies.

open as a page

In Laravel, what does storePublicly() change compared with store() on an UploadedFile, and what does it not change?

level: middleimportance: should knowfreq 32%

basics

~20 s

storePublicly() is store() with the visibility option forced to public: same generated name, same disk rules. It changes permissions or object access on the disk, but it does not make a file on a private local disk reachable by URL.

open as a page

In Laravel, what does JsonResource::withoutWrapping() change for a mobile API, and which resource responses still arrive wrapped in a data key?

level: seniorimportance: should knowfreq 32%

basics

~10 s

withoutWrapping() sets the static JsonResource::$wrap to null, so a plain outermost resource is sent bare. Paginated collections, responses with with() or additional() data, and data keys you write yourself still carry a data key.

open as a page

A Laravel API client posts JSON without an Accept header and gets a 302 redirect instead of JSON errors; what does expectsJson() check, and why?

level: seniorimportance: should knowfreq 38%

basics

~20 s

expectsJson() checks the response the client wants, not the body it sent: an AJAX request accepting anything, or JSON as the first Accept type. A JSON body with Accept: / fails both, so errors render as HTML redirects.

open as a page

A Laravel bookshop redirects after login with redirect()->to($request->input('return')); why is that an open redirect, and how do you fix it?

level: seniorimportance: should knowfreq 30%

basics

~20 s

Redirector::to() returns any string its URL generator considers a valid URL unchanged, including https:// and protocol-relative //host values, so a crafted return parameter sends users to another site. Redirect only to named routes, intended(), or a same-origin check.

open as a page

showing 1–30 of 37