PHP does not require explicit type definition in variable declaration. In this case, the type of a variable is determined by the value it stores. That is to say, if a string is assigned to variable $var, then $var is of type string . If afterwards an int value is assigned to $var, it will be of type int .
PHP may attempt to convert the type of a value to another automatically in certain contexts. The different contexts which exist are:
Note: When a value needs to be interpreted as a different type, the value itself does not change types.
To force a variable to be evaluated as a certain type, see the section on Type casting. To change the type of a variable, see the settype() function.
This is the context when using an arithmetical operator.
In this context if either operand is a float (or not interpretable as an int ), both operands are interpreted as float s, and the result will be a float . Otherwise, the operands will be interpreted as int s, and the result will also be an int . As of PHP 8.0.0, if one of the operands cannot be interpreted a TypeError is thrown.
This is the context when using echo , print , string interpolation, or the string concatenation operator.
In this context the value will be interpreted as string .
If the value cannot be interpreted a TypeError is thrown.
Prior to PHP 7.4.0, an E_RECOVERABLE_ERROR
was raised.
This is the context when using conditional statements, the ternary operator, or a logical operator.
In this context the value will be interpreted as bool .
This is the context when using bitwise operators.
In this context if all operands are of type string the result will also be a string . Otherwise, the operands will be interpreted as int s, and the result will also be an int . As of PHP 8.0.0, if one of the operands cannot be interpreted a TypeError is thrown.
This is the context when using a comparison operator.
The type conversions which occur in this context are explained in the Comparison with Various Types table.
This is the context when a value is passed to a typed parameter, property, or returned from a function which declares a return type.
In this context the value must be a value of the type. Two exceptions exist, the first one is: if the value is of type int and the declared type is float , then the integer is converted to a floating point number. The second one is: if the declared type is a scalar type, the value is convertable to a scalar type, and the coercive typing mode is active (the default), the value may be converted to an accepted scalar value. See below for a description of this behaviour.
Internal functions
automatically coerce null
to scalar types,
this behaviour is DEPRECATED as of PHP 8.1.0.
When strict_types
is not enabled, scalar type declarations
are subject to limited implicit type coercions.
If the exact type of the value is not part of the union, then the target type
is chosen in the following order of preference:
As an exception, if the value is a string and both int and float are part
of the union, the preferred type is determined by the existing
numeric string
semantics.
For example, for "42"
int is chosen,
while for "42.0"
float is chosen.
Note:
Types that are not part of the above preference list are not eligible targets for implicit coercion. In particular no implicit coercions to the null , false , and true types occur.
Example #1 Example of types being coerced into a type part of the union
<?php // int|string 42 --> 42 // exact type "42" --> "42" // exact type new ObjectWithToString --> "Result of __toString()" // object never compatible with int, fall back to string 42.0 --> 42 // float compatible with int 42.1 --> 42 // float compatible with int 1e100 --> "1.0E+100" // float too large for int type, fall back to string INF --> "INF" // float too large for int type, fall back to string true --> 1 // bool compatible with int [] --> TypeError // array not compatible with int or string // int|float|bool "45" --> 45 // int numeric string "45.0" --> 45.0 // float numeric string "45X" --> true // not numeric string, fall back to bool "" --> false // not numeric string, fall back to bool "X" --> true // not numeric string, fall back to bool [] --> TypeError // array not compatible with int, float or bool ?>
Type casting converts the value to a chosen type by writing the type within parentheses before the value to convert.
Example #2 Type Casting
<?php
$foo = 10; // $foo is an integer
$bar = (bool) $foo; // $bar is a boolean
var_dump($bar);
?>
The casts allowed are:
(int)
- cast to int (bool)
- cast to bool (float)
- cast to float (string)
- cast to string (array)
- cast to array (object)
- cast to object (unset)
- cast to NULL Note:
(integer)
is an alias of the(int)
cast.(boolean)
is an alias of the(bool)
cast.(binary)
is an alias of the(string)
cast.(double)
and(real)
are aliases of the(float)
cast. These casts do not use the canonical type name and are not recommended.
The (real)
cast alias has been deprecated as of PHP 8.0.0.
The (unset)
cast has been deprecated as of PHP 7.2.0.
Note that the (unset)
cast is the same as assigning the
value NULL to the variable or call.
The (unset)
cast is removed as of PHP 8.0.0.
The (binary)
cast and b
prefix exists
for forward support. Currently (binary)
and
(string)
are identical, however this may change and
should not be relied upon.
Note:
Whitespaces are ignored within the parentheses of a cast. Therefore, the following two casts are equivalent:
<?php
$foo = (int) $bar;
$foo = ( int ) $bar;
?>
Casting literal string s and variables to binary string s:
<?php
$binary = (binary) $string;
$binary = b"binary string";
?>
Instead of casting a variable to a string , it is also possible to enclose the variable in double quotes.
Example #3 Different Casting Mechanisms
<?php
$foo = 10; // $foo is an integer
$str = "$foo"; // $str is a string
$fst = (string) $foo; // $fst is also a string
// This prints out that "they are the same"
if ($fst === $str) {
echo "they are the same", PHP_EOL;
}
?>
It may not be obvious exactly what will happen when casting between certain types. For more information, see these sections:
Note: Because PHP supports indexing into string s via offsets using the same syntax as array indexing, the following example holds true for all PHP versions:
See the section titled String access by character for more information.Example #4 Using Array Offset with a String
<?php
$a = 'car'; // $a is a string
$a[0] = 'b'; // $a is still a string
echo $a; // bar
?>
Uneven division of an integer variable by another integer variable will result in a float by automatic conversion -- you do not have to cast the variables to floats in order to avoid integer truncation (as you would in C, for example):
$dividend = 2;
$divisor = 3;
$quotient = $dividend/$divisor;
print $quotient; // 0.66666666666667
Cast operators have a very high precedence, for example (int)$a/$b is evaluated as ((int)$a)/$b, not as (int)($a/$b) [which would be like intdiv($a,$b) if both $a and $b are integers].
The only exceptions (as of PHP 8.0) are the exponentiation operator ** [i.e. (int)$a**$b is evaluated as (int)($a**$b) rather than ((int)$a)**$b] and the special access/invocation operators ->, ::, [] and () [i.e. in each of (int)$a->$b, (int)$a::$b, (int)$a[$b] and (int)$a($b), the cast is performed last on the result of the variable expression].
Casting objects to arrays is a pain. Example:
<?php
class MyClass {
private $priv = 'priv_value';
protected $prot = 'prot_value';
public $pub = 'pub_value';
public $MyClasspriv = 'second_pub_value';
}
$test = new MyClass();
echo '<pre>';
print_r((array) $test);
/*
Array
(
[MyClasspriv] => priv_value
[*prot] => prot_value
[pub] => pub_value
[MyClasspriv] => second_pub_value
)
*/
?>
Yes, that looks like an array with two keys with the same name and it looks like the protected field was prepended with an asterisk. But that's not true:
<?php
foreach ((array) $test as $key => $value) {
$len = strlen($key);
echo "{$key} ({$len}) => {$value}<br />";
for ($i = 0; $i < $len; ++$i) {
echo ord($key[$i]) . ' ';
}
echo '<hr />';
}
/*
MyClasspriv (13) => priv_value
0 77 121 67 108 97 115 115 0 112 114 105 118
*prot (7) => prot_value
0 42 0 112 114 111 116
pub (3) => pub_value
112 117 98
MyClasspriv (11) => second_pub_value
77 121 67 108 97 115 115 112 114 105 118
*/
?>
The char codes show that the protected keys are prepended with '0円*0円' and private keys are prepended with '0円'.__CLASS__.'0円' so be careful when playing around with this.
If you want to convert a string automatically to float or integer (e.g. "0.234" to float and "123" to int), simply add 0 to the string - PHP will do the rest.
e.g.
$val = 0 + "1.234";
(type of $val is float now)
$val = 0 + "123";
(type of $val is integer now)
The object casting methods presented here do not take into account the class hierarchy of the class you're trying to cast your object into.
/**
* Convert an object to a specific class.
* @param object $object
* @param string $class_name The class to cast the object to
* @return object
*/
public static function cast($object, $class_name) {
if($object === false) return false;
if(class_exists($class_name)) {
$ser_object = serialize($object);
$obj_name_len = strlen(get_class($object));
$start = $obj_name_len + strlen($obj_name_len) + 6;
$new_object = 'O:' . strlen($class_name) . ':"' . $class_name . '":';
$new_object .= substr($ser_object, $start);
$new_object = unserialize($new_object);
/**
* The new object is of the correct type but
* is not fully initialized throughout its graph.
* To get the full object graph (including parent
* class data, we need to create a new instance of
* the specified class and then assign the new
* properties to it.
*/
$graph = new $class_name;
foreach($new_object as $prop => $val) {
$graph->$prop = $val;
}
return $graph;
} else {
throw new CoreException(false, "could not find class $class_name for casting in DB::cast");
return false;
}
}
Printing or echoing a FALSE boolean value or a NULL value results in an empty string:
(string)TRUE //returns "1"
(string)FALSE //returns ""
echo TRUE; //prints "1"
echo FALSE; //prints nothing!
There are some shorter and faster (at least on my machine) ways to perform a type cast.
<?php
$string='12345.678';
$float=+$string;
$integer=0|$string;
$boolean=!!$string;
?>
Type casting in expressions is executed first.
The casting is assigned to the value, not to the expression result.
Examples:
<?php
$string = "777";
var_dump( $string === 777 ); // FALSE
var_dump( (int) $string === 777 ); // TRUE
var_dump( ( (int) $string ) === 777 ); // TRUE
var_dump( (int) ( $string === 777 ) ); // 0
?>
This PHP documentation is very thorough.
An observation about comments, maybe they lost sense when become old, and the page changes, so, should be signaled this condition, or add a link to the document version when the comment was made.