Verbose Type Functions
debt(d5/e1/b3/t5)
Closest to 'specialist tool catches it' (d5). The detection_hints list phpstan and rector as the tools that flag redundant type checks (e.g., is_array() on an array-typed parameter). These are not default linters but specialist static analysis tools, placing this squarely at d5.
Closest to 'one-line patch or single-call swap' (e1). The quick_fix says to replace verbose type-check functions with native type declarations — each instance is a single-line removal or substitution of a redundant call. Rector can automate many of these, reinforcing e1.
Closest to 'localised tax' (b3). Redundant type checks add noise at the point of use (one function/component), but they don't impose a cross-cutting structural cost. The rest of the codebase is largely unaffected. Applies to web, cli, and queue-worker contexts but each occurrence is an isolated stylistic cost, not an architectural load-bearing choice.
Closest to 'notable trap' (t5). The misconception field directly states the trap: developers believe intval() is safer than (int) casting for validation, when in fact both truncate floats and silently convert non-numeric strings to 0 — neither validates. This is a documented, well-known gotcha that many PHP developers eventually learn, matching the t5 anchor.
Also Known As
TL;DR
Explanation
Verbose type functions have their place but are often overused. intval() for casting is verbose vs (int); is_array() checks in PHP 8 with typed parameters are redundant since the type system already guarantees the type. intval($x, 10) is correct for base-10 parsing of strings, but (int)$x is sufficient for casting known numeric values. Similarly, strval() vs (string), boolval() vs (bool). The exception: intval() for parsing user input from strings where the base matters, or when chaining with array_map().
Common Misconception
Why It Matters
Common Mistakes
- is_array($arr) where $arr is declared as array — PHP already knows.
- intval($id) where $id is already typed as int — cast is redundant.
- strval($str) where $str: string — no-op cast adds clutter.
- Not using (int)$_GET['id'] for superglobal values — those do need explicit casting.
Avoid When
- Avoid intval(), strval(), floatval() when a simple cast suffices — they add noise without benefit.
- Do not use settype() — it modifies variables in place and reduces clarity.
When To Use
- Use (int), (float), (string), (bool) casts or intval()/floatval() only when you explicitly need type coercion.
- Prefer type declarations on function parameters over manual casting inside the function body.
Code Examples
// Redundant type functions with typed parameters:
function process(array $items, int $limit): array {
if (!is_array($items)) return []; // Type system already guarantees this
$count = intval($limit); // $limit is already int
$str = strval($count); // Verbose cast
return array_slice($items, 0, $count);
}
// Clean — let the type system do its job:
function process(array $items, int $limit): array {
return array_slice($items, 0, $limit); // Types guaranteed by declaration
}
// Casting superglobals — appropriate use:
$id = (int) ($_GET['id'] ?? 0);
$name = (string) ($_POST['name'] ?? '');
$price = (float) ($_POST['price'] ?? 0);
// Validate user input properly:
$id = filter_var($_GET['id'], FILTER_VALIDATE_INT);
if ($id === false) throw new InvalidArgumentException('Invalid ID');