skip to content

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

level: middleimportance: should knowfreq 42%

answer

  1. filter_var with FILTER_VALIDATE_BOOLEAN
  2. integer() is a plain int cast
  3. defaults cover absent keys only
  4. date() throws InvalidFormatException
  5. enum() falls back via tryFrom

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.

solid answer

~40 s

The typed readers convert raw strings without validating them. `boolean('remote')` runs `filter_var(..., FILTER_VALIDATE_BOOLEAN)`: `1`, `true`, `on` and `yes` give `true`, anything else `false`, and the default (`false`) applies only when the key is absent. `integer('per_page', 20)` is `(int)` on the value, so `abc` gives `0`, `12abc` gives `12`, and an emptied field gives `0`, not 20. `date('posted_after')` returns `null` when the field is not filled, parses leniently with Carbon, or uses a format if given, and throws `Carbon\Exceptions\InvalidFormatException` for garbage. `enum('type', JobType::class)` returns the default (`null`) when the value is empty, the class is not backed, or `tryFrom()` fails. Validate first; these helpers are for shaping trusted input.

code

php · 16 lines
php
<?php

use App\Enums\JobType;
use Illuminate\Http\Request;

// ?remote=on&per_page=abc&posted_after=yesterday&type=freelance
public function index(Request $request)
{
    $remote = $request->boolean('remote');                 // true ("on")
    $perPage = $request->integer('per_page', 20);          // 0, not 20: (int) 'abc'
    $safePerPage = $request->clamp('per_page', 10, 50, 20); // 20 fallback, clamped to 10..50
    $since = $request->date('posted_after');               // Carbon, parsed leniently
    $type = $request->enum('type', JobType::class, JobType::FullTime); // FullTime: 'freelance' is no case

    return compact('remote', 'perPage', 'safePerPage', 'since', 'type');
}

go deeper

for a junior

Recall that boolean() understands on, yes, true and 1, that date() gives a Carbon instance, and that enum() maps a string to a backed enum case.

for a middle

Explain each helper's failure mode: absent keys use the default, empty fields cast to 0 or false, date() throws, enum() falls back through tryFrom.

for a senior

Spot the 500s and silent zeroes these helpers cause on unvalidated input, and pair them with validation or clamp() on public search endpoints.

for a principal

Decide where conversion lives: typed readers in controllers, validated data objects or form requests, and make the choice consistent across the codebase.

## Why typed readers exist Everything that arrives over HTTP is a string, an array of strings or, for JSON payloads, a scalar the client chose. Laravel's `Illuminate\Http\Request` inherits a family of **typed readers** from the `InteractsWithData` trait that convert a field into a PHP type in one call. They are convenient, but each has precise rules for absent, empty and malformed values, and those rules are what a middle-level interview checks. The running example is a job-board search: `?remote=on&per_page=abc&posted_after=yesterday&type=contract`. ## The four helpers at a glance | Helper | Signature | Absent key | Empty (null) value | Malformed value | |---|---|---|---|---| | `boolean()` | `boolean($key = null, $default = false)` | `$default` passed through `filter_var` | `false` | `false` | | `integer()` | `integer($key, $default = 0)` | `(int) $default` | `0` | `(int)` cast: `'abc'` gives `0`, `'12abc'` gives `12` | | `date()` | `date($key, $format = null, $tz = null)` | `null` | `null` | throws `InvalidFormatException` | | `enum()` | `enum($key, $enumClass, $default = null)` | `$default` | `$default` | `$default` | ## boolean() for checkboxes `boolean()` calls `filter_var($value, FILTER_VALIDATE_BOOLEAN)`. PHP's filter returns `true` for `"1"`, `"true"`, `"on"` and `"yes"` and `false` for everything else, including values it cannot interpret, because the method does not pass `FILTER_NULL_ON_FAILURE`. So `remote=maybe` silently reads as `false`. An unchecked checkbox is not sent, so the default applies; a common form pattern places `<input type="hidden" name="remote" value="0">` before the checkbox so the key is always present. ## integer() and float() are casts, not parsers `integer()` is literally `(int) $this->input($key, $default)`. Three consequences follow: 1. The default is used only when the key is **absent**. A field emptied to `null` by `ConvertEmptyStringsToNull` casts to `0`. 2. Text casts to `0`, and a leading number wins: `'12abc'` becomes `12`, `'3.9'` becomes `3`. 3. Nothing is range-checked, so `per_page=100000` passes straight through. The laravel/docs page says a failed cast returns the default you specify; the pinned source casts with `(int)`, so a failed cast returns `0`. For bounded numbers the trait also offers `clamp($key, $min, $max, $default = 0)`, which substitutes the default for non-numeric input and clamps the result into range. ## date() and interval() can throw `date()` first checks `isNotFilled()`; a missing or empty field returns `null`. Otherwise: - **Without a format**, it calls `Date::parse()`, which delegates to Carbon's lenient parser, so relative strings such as `yesterday` or `next monday` succeed. - **With a format**, it calls `Date::createFromFormat($format, $value, $tz)`. - **On bad input**, both paths throw `Carbon\Exceptions\InvalidFormatException`, a subclass of `InvalidArgumentException`. Unvalidated, that becomes a 500 error. `interval()` follows the same pattern for `CarbonInterval` values. ## enum() and enums() never throw `enum('type', JobType::class)` returns the default when the field is not filled, when the class is not a **backed** enum, or when `JobType::tryFrom($value)` returns `null`. `enums('types', JobType::class)` maps an array of values and drops the invalid ones. The related `whenEnum()` runs a callback only for a valid case. ## Practical guidance - **Validate before converting** anything whose failure mode is an exception (`date()`, `interval()`) or a silent wrong value (`integer()` returning `0`). - **Use `boolean()` for flags** and `enum()` for fixed choices, so controllers compare typed values rather than strings. - **Treat defaults as "absent" defaults**; if an empty field must also fall back, write `$request->integer('per_page') ?: 20` or use `clamp()`. - **Remember `string()`/`str()`** return a `Stringable`, and `array()` casts to an array, returning `[]` for an absent key. ## A note on JSON payloads When an API client posts JSON, values keep their JSON types. `{"remote": false}` reaches `boolean()` as a real boolean, which `filter_var` returns unchanged, and `{"per_page": 25}` reaches `integer()` as an int. The helpers still apply their rules, so the same controller serves both HTML forms, where everything is a string, and JSON clients. The trap is in the other direction: a JSON `null` is a present key, so `integer('per_page', 20)` returns `0` and `enum()` returns its default, exactly as for an emptied form field.

  • A user submits posted_after=2026-09-01 and the controller calls $request->date('posted_after', 'd/m/Y'). What happens?
    The value is filled, so `date()` calls `Date::createFromFormat('d/m/Y', ...)`. The value does not match the format, so Carbon throws `Carbon\Exceptions\InvalidFormatException`, an `InvalidArgumentException`. Without validation earlier in the request, that surfaces as a server error. Validate the field with a date rule first, then read it with `date()`.
  • When would you use $request->clamp() instead of integer() for a per_page parameter?
    Whenever the number must stay in a range. `clamp('per_page', 10, 50, 20)` replaces a non-numeric value with the default and then clamps it between 10 and 50, while `integer()` returns `0` for text and passes huge values through, which can page thousands of rows.

saying these in an interview costs you the question

  • integer('per_page', 20) returns 20 when the value is not numeric
  • boolean() returns null for values it cannot recognise
  • date() returns null when the format does not match
  • enum() throws a ValueError for an unknown value
  • The typed helpers validate input, so no rules are needed