intval() / Type Casting
debt(d5/e3/b3/t7)
Closest to 'specialist tool catches it' (d5). The detection_hints list phpstan and semgrep — both specialist static analysis tools — as able to catch the misuse pattern (intval() without base parameter on user input, or used for validation). This is not caught by the compiler or a default linter, but is reachable with configured specialist tooling.
Closest to 'simple parameterised fix' (e3). The quick_fix states: use intval($var, 10) with explicit base 10, or swap to filter_var with FILTER_VALIDATE_INT. This is a small, localised replacement — find all intval() calls validating input and swap the pattern — touching one call site at a time but potentially spread across multiple files, landing between e1 and e3, scored e3.
Closest to 'localised tax' (b3). The applies_to contexts are web, cli, and queue-worker — broad in theory — but the misuse is at individual call sites rather than an architectural choice. Each affected call site pays its own small tax; the rest of the codebase is largely unaffected. No strong gravitational pull on future design.
Closest to 'serious trap' (t7). The misconception field states developers believe intval() validates that a value is a valid integer, when it actually silently returns 0 for non-numeric strings like 'abc'. This directly contradicts the intuitive reading of the function name ('validate as int') and the behaviour of similar constructs in other languages or PHP's own filter_var — intval('abc') === 0 is a silent, dangerous result that contradicts developer expectations, especially when 0 may itself be a valid value (e.g. a valid ID).
Also Known As
TL;DR
Explanation
intval($value) converts a value to integer, (int)$value does the same with less overhead. For values that must be numeric (database IDs, pagination offsets, quantities), casting is often the simplest and safest validation — non-numeric strings become 0, so you can immediately check if the result is valid. However, type casting is not a substitute for proper validation when the allowed range matters: intval("999999999999") silently overflows on 32-bit systems. Combine with range checks for critical values.
Common Misconception
Why It Matters
Common Mistakes
- Using intval() to validate that input is a number — it returns 0 for 'abc', which may be a valid ID.
- Not specifying the base parameter — intval('0x1A') returns 0 in base 10, not 26.
- Using intval() for large numbers that exceed PHP_INT_MAX — silent truncation.
- Using (int) cast instead of intval() for readability — they are equivalent but intval() with a base argument is more explicit.
Code Examples
// intval() used for validation — accepts 'abc' as 0:
$id = intval($_GET['id']);
$user = User::find($id); // find(0) might return first user or null — not an error
// Correct validation:
if (!ctype_digit($_GET['id'])) throw new InvalidArgumentException();
$id = (int) $_GET['id'];
// intval() converts to integer — stops at first non-numeric char
intval('42abc'); // 42
intval('abc'); // 0
intval('0x1A', 16); // 26 (hex with base)
intval('0777', 8); // 511 (octal)
// For strict validation — use filter_var:
\$id = filter_var(\$_GET['id'], FILTER_VALIDATE_INT);
if (\$id === false || \$id < 1) abort(400);
// Simple cast — fastest for basic use:
\$page = max(1, (int) (\$_GET['page'] ?? 1));
\$userId = (int) \$_POST['user_id'];