PHP in_array strict mode: keep identifiers from matching the wrong type
A permission list contains integer identifiers, while a request supplies strings. If membership testing quietly converts types, a value can match even though it violates the input contract. The fix starts before the array search.
Demonstrate both comparisons
<?php
$allowedIds = [12, 45, 81];
assert(in_array('12', $allowedIds) === true);
assert(in_array('12', $allowedIds, true) === false);
assert(in_array(12, $allowedIds, true) === true);
echo "strict membership distinguishes types", PHP_EOL;
The third argument requests a strict comparison. This example intentionally treats an integer identifier and a string identifier as different representations.
Normalize once at the boundary
For a form where decimal strings are expected, validate the representation and range, then convert it once. Do not spread casts throughout policies and queries. Casting arbitrary text to an integer can produce a value that never existed in the request contract.
For external identifiers, conversion may be the wrong design entirely. A supplier code such as "0012" is often a string whose leading zeroes matter. Keep those codes as strings in storage, validation, logs, and comparisons.
Membership is not authorization
Even a correctly typed identifier must belong to the current user's account or tenant. A global allowlist of existing IDs does not establish that relationship. In an application, load the resource through its tenant-scoped query and enforce the relevant policy.
Useful tests include integer 12, string "12", string "0012", null, an array, and an identifier belonging to another account. The last test checks authorization, which the small standalone example does not attempt to provide.
Use strict membership when you already know the representation you expect. If you find yourself disabling strict mode to make a failing input pass, return to the boundary contract and resolve the mismatch there. PHP's in_array reference documents strict type checking.