skip to content

In PHP, how do intval(), settype() and the (array) cast differ from a plain (int) cast?

level: middleimportance: should knowfreq 24%

answer

  1. intval: same result, plus a base
  2. base 0 detects 0x and 0 prefixes
  3. settype changes the variable in place, returns true
  4. (array) wraps scalars; null gives []
  5. object to array: mangled private keys

basics

~20 s

intval() equals (int) but takes a base, so intval('1A', 16) is 26. settype() converts a variable in place and returns true. (array) wraps a scalar in a one-element array, turns null into [] and lists an object's properties.

solid answer

~40 s

`intval($value)` with the default base 10 gives exactly what `(int)` gives; its extra is the **`$base`** parameter: `intval('1A', 16)` is `26`, `intval('42', 8)` is `34`, and base `0` detects the base from the prefix, so `intval('0x1A', 0)` is `26`. The base only matters for strings. Being a function, `intval` can also be passed as a callable, as in `array_map(intval(...), $row)`. `settype($var, 'int')` converts the **variable itself** by reference, using a type name string (`'int'`, `'float'`, `'string'`, `'bool'`, `'array'`, `'object'`, `'null'` and the long aliases), returns `true`, and throws `ValueError` for an unknown name. `(array)` wraps a scalar in a one-element array (`(array) 'x'` is `['x']`), turns `null` into `[]` and leaves arrays unchanged; for an object it returns its properties, with private and protected names mangled with NUL-byte prefixes.

code

php · 13 lines
php
<?php
declare(strict_types=1);

var_dump(intval('1A', 16), intval('0x1A', 0), intval('0x1A')); // int(26) int(26) int(0)

$qty = '12';
var_dump(settype($qty, 'int'), $qty);  // bool(true) int(12)

var_dump((array) 'BX-1');  // [0 => 'BX-1']
var_dump((array) null);    // []

$fields = ['7', '0', '15'];
var_dump(array_map(intval(...), $fields)); // [7, 0, 15]

go deeper

for a junior

Know that intval() matches (int) but accepts a base, settype() changes the variable itself, and (array) wraps a scalar in an array.

for a middle

Explain base 0 prefix detection in intval(), settype()'s by-reference signature, return value and ValueError, and the three (array) rules for scalars, null and arrays.

for a senior

Choose the right conversion tool in real code and flag misuses such as (array) on objects for export or settype() where a cast reads better.

for a principal

Keep conversion explicit and centralised in a codebase, so parsing with bases, list normalisation and validation each happen in one known place.

## Several tools, one conversion engine PHP offers casts, conversion functions and `settype()`. They share the same conversion rules underneath, so the results agree; what differs is the **interface**: extra parameters, whether the original variable changes, and whether the tool can be passed around as a callable. ## intval() versus (int) `intval(mixed $value, int $base = 10): int` returns the same integer as an `(int)` cast when called with the default base. Its additions: - **A base for strings.** `intval('42', 8)` reads octal and returns `34`; `intval('1A', 16)` returns `26`; bases up to 36 are allowed, so `intval('1ya', 36)` is `2530`. - **Base 0 detects the prefix.** With base `0`, a `0x` prefix means hexadecimal, `0b` binary and a leading `0` octal, so `intval('0x1A', 0)` is `26`, while `intval('0x1A')` and `(int) '0x1A'` are both `0`. - **The base is ignored for non-strings.** `intval(42, 8)` is `42`, because the value is already an integer. - **It is a function**, so it can be used as a callable: `array_map(intval(...), $csvRow)` converts every field of a row. Like the cast, `intval()` never throws for strings: garbage gives `0`. The siblings `floatval()`, `boolval()` and `strval()` mirror `(float)`, `(bool)` and `(string)` in the same way, without a base. ## settype(): convert the variable itself `settype(mixed &$var, string $type): bool` takes the variable **by reference** and converts it in place: ```php $qty = '12'; settype($qty, 'int'); // $qty is now int(12); the call returns true ``` Things to know: | Point | Detail | |---|---| | Type names | `'int'`/`'integer'`, `'float'`/`'double'`, `'string'`, `'bool'`/`'boolean'`, `'array'`, `'object'`, `'null'` (case-insensitive) | | Unknown name | throws `ValueError`: argument #2 must be a valid type | | `'resource'` | throws `ValueError`: cannot convert to resource type | | Return value | `true` on success | `settype()` is useful when the target type is only known as a string at runtime. In ordinary code, `$qty = (int) $qty;` says the same thing more clearly. ## The (array) cast `(array)` follows three rules: 1. **Scalars** (int, float, string, bool) become a **one-element array** with key `0`: `(array) 'BX-1'` is `['BX-1']`. The manual puts it as `(array) $scalarValue` being exactly `array($scalarValue)`. 2. **`null`** becomes an **empty array**, `[]`. That makes `(array) $maybeList` a common idiom for "iterate this whether it is a list, a single value or null". 3. **Arrays** are returned unchanged. For **objects**, `(array)` returns the object's properties as keys, including private and protected ones, with **mangled names**: a private property `$sku` of class `Item` appears under the key `"\0Item\0sku"`, and a protected one under `"\0*\0sku"`. Uninitialized typed properties are left out. The mangled keys are why `(array) $object` is rarely what you want for serialising or exporting data; `get_object_vars()` returns the properties visible from the calling scope with clean names. ## What (int) and intval() do with non-strings The integer conversion is defined for every type, which matters when a value is not the string you expected: | Input | `(int)` / `intval()` | |---|---| | `true` / `false` | `1` / `0` | | `null` | `0` | | `3.9` / `-3.9` | `3` / `-3` (truncated toward zero) | | `[]` | `0` | | any non-empty array | `1` | The array rows show why casting a value that is sometimes a list is dangerous: `(int) ['12']` is `1`, not `12`. ## Choosing between them - Converting a validated value: **`(int)`**, `(float)`, `(string)`, `(bool)`. - Parsing a hex, octal or other-base string: **`intval($s, $base)`**. - Mapping over many values: **`intval(...)`** or another function as a callable. - Converting a variable when the type name arrives as data: **`settype()`**. - Normalising "one or many or none" into a list: **`(array)`**. None of these validate. `intval('n/a')` is `0`, `settype($x, 'int')` on `'1,200'` gives `1`, and `(array)` accepts anything. Validation is a separate step that has to happen first.

  • What is the difference between intval('012') and intval('012', 0)?
    With the default base 10, leading zeros are just digits, so `intval('012')` is `12`. With base `0`, `intval()` detects the base from the prefix, and a leading `0` means octal, so `intval('012', 0)` is `10`. An `(int)` cast always behaves like the base-10 form.
  • Why is (array) $maybeItems a common idiom, and when does it go wrong?
    Because it normalises three shapes in one step: `null` becomes `[]`, a single scalar becomes a one-element list, and an array stays as it is, so a `foreach` works on all of them. It goes wrong when the value is an object: `(array)` then returns the object's properties with mangled private and protected keys, not a list of items.

saying these in an interview costs you the question

  • Says intval('0x1A') returns 26 without passing a base.
  • Believes settype() returns the converted value like a cast does.
  • Thinks (array) null gives [null] rather than an empty array.
  • Claims intval() throws for non-numeric strings while (int) does not.
  • Expects (array) $object to give clean property names for private properties.