PHP Casting
What Is Casting? In simple terms: Casting means converting a value from one type to another on purpose — for example, turning the text "42" into the number 42 . Technically: Type casting is an explici
What Is Casting?
In simple terms: Casting means converting a value from one type to another on purpose — for example, turning the text "42" into the number 42.
Technically: Type casting is an explicit type conversion. You write the target type in parentheses before a value, such as (int) $value, and PHP returns a new value of that type. The original variable is not changed.
PHP also converts types automatically in many situations (for example, when you add a string to a number). That automatic behavior is called type juggling and has its own lesson. Casting is the explicit counterpart: you decide when and how a conversion happens.
Why Casting Is Needed
Data often arrives with the wrong type for what you want to do with it:
- Form fields, URL parameters, cookies, and CSV values are always strings.
- Some database drivers return numbers as strings.
- JSON may contain numbers where your code needs strings (or the reverse).
- Functions with strict type declarations require exact types.
Casting makes the conversion visible in the code, so a reader knows that a type change is intentional.
Cast Operators
Syntax
\$result \= (type) \$value;
| Cast | Converts To | Example | Result |
|---|---|---|---|
(int) | Integer | (int) "42" | 42 |
(float) | Float | (float) "3.5" | 3.5 |
(string) | String | (string) 42 | "42" |
(bool) | Boolean | (bool) "hello" | true |
(array) | Array | (array) "PHP" | ["PHP"] |
(object) | Object (stdClass) | (object) ['a' => 1] | object with property a |
Version Notes
- Long aliases are deprecated.
(integer),(double),(boolean), and(binary)are older spellings of(int),(float),(bool), and(string). Since PHP 8.5 they produce a deprecation notice, and PHP 9 is expected to stop recognizing them. Always use the short forms. - Removed casts.
(real)and(unset)were removed in PHP 8.0 and cause a parse error. Use(float)and assignnullinstead.
Example
<?php
\$input \= "42";
\$number \= (int) \$input;
var_dump(\$input);
var_dump(\$number);
Output
string(2) "42"
int(42)
The cast returns a new integer. $input still holds the string "42".
Casting to Integer: (int)
Rules
<?php
var_dump((int) "123");
var_dump((int) " 123");
var_dump((int) "123abc");
var_dump((int) "abc123");
var_dump((int) "");
var_dump((int) 12.99);
var_dump((int) -12.99);
var_dump((int) "1e3");
var_dump((int) true);
var_dump((int) false);
var_dump((int) null);
Output
int(123)
int(123)
int(123)
int(0)
int(0)
int(12)
int(-12)
int(1000)
int(1)
int(0)
int(0)
What These Results Mean
| Input | Behavior |
|---|---|
| Numeric string | Converted to the number; leading whitespace is ignored |
String starting with digits ("123abc") | Uses the leading number, ignores the rest |
String not starting with a number ("abc123", "") | Becomes 0 |
| Float | Truncated toward zero — 12.99 becomes 12, not 13 |
Numeric string in exponent form ("1e3") | Interpreted as the number 1000 |
true / false / null | 1 / 0 / 0 |
Casting Never Fails — and That Is a Risk
(int) always returns an integer, even for meaningless input. (int) "abc" silently becomes 0, and (int) "12abc" silently becomes 12. This is convenient for trusted data, but dangerous for validation:
<?php
\$quantity \= (int) "five"; // 0 — no error, no warning
For user input, validate first and convert second:
<?php
\$quantity \= filter_var("five", FILTER_VALIDATE_INT);
if (\$quantity \=== false) {
echo "Please enter a whole number.";
}
Output
Please enter a whole number.
filter_var() both validates and converts: it returns an int for valid input and false otherwise. See PHP Numbers for more validation options.
Rounding Before Casting
Because (int) truncates, round first when you need the nearest whole number:
<?php
var_dump((int) 7.8);
var_dump((int) round(7.8));
Output
int(7)
int(8)
Casting to Float: (float)
<?php
var_dump((float) "3.75");
var_dump((float) "10");
var_dump((float) "2.5e2");
var_dump((float) "12.5kg");
var_dump((float) "1,250.50");
var_dump((float) 7);
Output
float(3.75)
float(10)
float(250)
float(12.5)
float(1)
float(7)
The same "leading number" rule applies. Note the fifth result: "1,250.50" becomes 1.0 because conversion stops at the comma. Formatted numbers must be cleaned before conversion, for example with str_replace(',', '', $value) or filter_var($value, FILTER_VALIDATE_FLOAT, FILTER_FLAG_ALLOW_THOUSAND).
Casting to String: (string)
<?php
var_dump((string) 42);
var_dump((string) 3.0);
var_dump((string) 0.1);
var_dump((string) true);
var_dump((string) false);
var_dump((string) null);
Output
string(2) "42"
string(1) "3"
string(3) "0.1"
string(1) "1"
string(0) ""
string(0) ""
Details
- Floats with no fractional part lose the
.0:(string) 3.0is"3". truebecomes"1";falseandnullbecome an empty string.- Since PHP 8.0, float-to-string conversion always uses
.as the decimal separator, regardless of the locale.
Arrays and Objects
<?php
\$tags \= ['php', 'mysql'];
echo (string) \$tags;
Output
PHP Warning: Array to string conversion in /path/script.php on line 3
Array
An array cannot be meaningfully converted to a string, so PHP produces the text Array and a warning. Use implode() or json_encode() instead.
An object can be cast to a string only if its class defines a __toString() method; otherwise PHP throws an Error:
<?php
class Money
{
public function __construct(private int \$paise) {}
public function __toString(): string
{
return '₹' . number_format(\$this->paise / 100, 2);
}
}
\$price \= new Money(149900);
echo (string) \$price . "\n";
echo "Price: \$price\n";
Output
₹1,499.00
Price: ₹1,499.00
__toString() is called whenever the object is used as a string — in casts, echo, interpolation, and concatenation. Magic methods are covered in Magic Methods.
Casting to Boolean: (bool)
(bool) converts any value to true or false using PHP's truthiness rules: false, 0, 0.0, "", "0", [], and null become false; everything else becomes true.
<?php
var_dump((bool) "0");
var_dump((bool) "0.0");
var_dump((bool) "false");
var_dump((bool) []);
var_dump((bool) [0]);
Output
bool(false)
bool(true)
bool(true)
bool(false)
bool(true)
(bool) "false" is true, because the string is not empty. To interpret text such as "yes", "no", "on", or "false", use filter_var($value, FILTER_VALIDATE_BOOLEAN). All rules are covered in PHP Booleans.
Casting to Array: (array)
Scalars and Null
<?php
var_dump((array) "PHP");
var_dump((array) 42);
var_dump((array) null);
var_dump((array) ['already', 'an', 'array']);
Output
array(1) {
[0]=>
string(3) "PHP"
}
array(1) {
[0]=>
int(42)
}
array(0) {
}
array(3) {
[0]=>
string(7) "already"
[1]=>
string(2) "an"
[2]=>
string(5) "array"
}
- A scalar value becomes a one-element array.
nullbecomes an empty array.- An array stays unchanged.
Practical Use: Accepting One Value or Many
<?php
function addTags(string|array \$tags): array
{
\$tags \= (array) \$tags;
return array_map('strtolower', \$tags);
}
print_r(addTags('PHP'));
print_r(addTags(['PHP', 'MySQL']));
Output
Array
(
[0] \=> php
)
Array
(
[0] \=> php
[1] \=> mysql
)
(array) normalizes both inputs into an array, so the rest of the function handles a single case. This pattern is common for options that accept either one value or a list.
Objects to Arrays
Casting an object to an array produces an array of its properties:
<?php
class User
{
public string \$name \= 'Asha';
protected string \$role \= 'editor';
private string \$password \= 'secret';
}
\$data \= (array) new User();
foreach (array_keys(\$data) as \$key) {
echo str_replace("\0", '\0', \$key) . "\n";
}
Output
name
\0*\0role
\0User\0password
Public properties keep their names. Protected properties are prefixed with \0*\0, and private properties with \0ClassName\0, where \0 is an invisible null byte (made visible here with str_replace()). These prefixes make the result awkward to use, and the cast exposes private data such as passwords.
To export object data, use public methods or get_object_vars() inside the class, and never pass objects containing secrets to output or logs via a cast.
Casting to Object: (object)
<?php
\$config \= (object) [
'host' \=> 'localhost',
'port' \=> 3306,
];
echo \$config->host . ":" . \$config->port . "\n";
var_dump(\$config instanceof stdClass);
Output
localhost:3306
bool(true)
An associative array becomes a stdClass object whose properties match the array keys. Scalars become an object with a single property named scalar:
<?php
var_dump((object) "hello");
Output
object(stdClass)#1 (1) {
["scalar"]=>
string(5) "hello"
}
(The object ID #1 may differ.)
(object) is convenient for quick data containers, but for structured data used throughout an application, a real class with typed properties is clearer and safer.
Conversion Functions
PHP also provides functions that perform the same conversions:
| Function | Equivalent Cast | Extra Capability |
|---|---|---|
intval($v, $base) | (int) | Optional base, e.g. intval("ff", 16) → 255 |
floatval($v) | (float) | — |
strval($v) | (string) | — |
boolval($v) | (bool) | — |
settype($var, $type) | — | Changes the variable in place |
Why Use Functions Instead of Casts?
Functions can be passed as callbacks, which casts cannot:
<?php
\$prices \= ["499", "1299", "89"];
\$numbers \= array_map('intval', \$prices);
var_dump(\$numbers);
echo array_sum(\$numbers) . "\n";
Output
array(3) {
[0]=>
int(499)
[1]=>
int(1299)
[2]=>
int(89)
}
1887
array_map('intval', ...) converts every element. A cast like (int) cannot be passed by name; you would need fn($p) => (int) $p.
settype() Modifies the Variable
<?php
\$value \= "123abc";
settype(\$value, "integer");
var_dump(\$value);
Output
int(123)
Unlike a cast, settype() changes the variable itself and returns true on success. It accepts type names such as "integer", "int", "float", "string", "boolean", "bool", "array", "object", and "null". Casts are usually clearer because the conversion is visible where the value is used.
Casting and Strict Types
When a file declares declare(strict_types=1);, PHP stops converting scalar arguments automatically when calling functions with type declarations. Explicit casts are still allowed and become the standard way to convert data at the boundaries of your code:
<?php
declare(strict_types=1);
function calculateTotal(int \$quantity, float \$unitPrice): float
{
return \$quantity * \$unitPrice;
}
\$quantityInput \= "3"; // from a form
\$priceInput \= "249.50"; // from a form
// calculateTotal(\$quantityInput, \$priceInput); // TypeError in strict mode
echo calculateTotal((int) \$quantityInput, (float) \$priceInput);
Output
748.5
The casts convert the form strings into the types the function requires. In real code, validate the inputs (with filter_var()) before casting. Strict types are covered in Strict Types.
Practical Example: Normalizing Request Parameters
A listing page receives query parameters such as ?page=3&per_page=25abc&featured=0&tags=php. Each value arrives as a string (or is missing).
<?php
function readListingOptions(array \$query): array
{
\$page \= filter_var(\$query['page'] ?? '', FILTER_VALIDATE_INT, [
'options' \=> ['min_range' \=> 1],
]);
\$perPage \= filter_var(\$query['per_page'] ?? '', FILTER_VALIDATE_INT, [
'options' \=> ['min_range' \=> 1, 'max_range' \=> 100],
]);
return [
'page' \=> \$page \=== false ? 1 : \$page,
'perPage' \=> \$perPage \=== false ? 20 : \$perPage,
'featured' \=> (bool) (int) (\$query['featured'] ?? 0),
'tags' \=> array_map('strval', (array) (\$query['tags'] ?? [])),
];
}
\$options \= readListingOptions([
'page' \=> '3',
'per_page' \=> '25abc',
'featured' \=> '0',
'tags' \=> 'php',
]);
var_dump(\$options);
Output
array(4) {
["page"]=>
int(3)
["perPage"]=>
int(20)
["featured"]=>
bool(false)
["tags"]=>
array(1) {
[0]=>
string(3) "php"
}
}
Step-by-Step Explanation
pageis validated withfilter_var()and a minimum of 1."3"is valid and becomesint(3).per_pagemust be between 1 and 100."25abc"is not a valid integer, so the default20is used. A plain(int)cast would have silently accepted it as25.featuredis cast with(int)and then(bool). Casting tointfirst guarantees that values such as"0"and"1"map tofalseandtrue(and that"0.0"or"00"are treated as0instead of being truthy strings).tagsmay arrive as a single string (?tags=php) or an array (?tags[]=php&tags[]=mysql).(array)normalizes both, andarray_map('strval', ...)ensures every element is a string.
The result is an array of correctly typed values that the rest of the application can trust.
Common Mistakes
Using Casts as Validation
Effect: (int) "abc" becomes 0, and (int) "12abc" becomes 12, without any error.
Fix: Validate with filter_var() before using the value.
Expecting (int) to Round
Effect: (int) 9.99 is 9.
Fix: Use (int) round($value), or floor()/ceil() deliberately.
Casting Formatted Numbers
Effect: (float) "1,250.50" is 1.0.
Fix: Remove separators or use a validating filter with FILTER_FLAG_ALLOW_THOUSAND.
Casting "false" to Bool
Effect: true, because the string is not empty.
Fix: filter_var($value, FILTER_VALIDATE_BOOLEAN).
Casting Objects With Private Data to Arrays
Effect: Private properties (including secrets) appear in the result with null-byte prefixes.
Fix: Expose data through explicit methods; never dump or log such casts.
Using Deprecated or Removed Cast Names
Effect: Deprecation notices for (integer), (double), (boolean), (binary) in PHP 8.5; parse errors for (real) and (unset).
Fix: Use (int), (float), (bool), (string), and assign null directly.
Best Practices
- Use the short cast forms:
(int),(float),(string),(bool),(array),(object). - Cast at the boundaries of your code — where external data enters — and work with correct types everywhere else.
- Validate before casting untrusted input; cast only values you already know are valid.
- Round explicitly before casting floats to integers when rounding is intended.
- Use
(array)to accept "one or many" values, andintval/strvalas callbacks witharray_map(). - Prefer real classes over
(object)casts for data used across the application.
Official reference: https\://www.php.net/manual/en/language.types.type-juggling.php#language.types.typecasting