Манипуляции с типами
PHP не требует (и не поддерживает) явного типа при определении переменной; тип переменной определяется по контексту, в котором она используется. То есть, если вы присвоите значение типа string переменной $var, то $var станет строкой. Если вы затем присвоите $var целочисленное значение, она станет целым числом.
Примером автоматического преобразования типа является оператор сложения '+'. Если какой-либо из операндов является float, то все операнды интерпретируются как float, и результатом также будет float. В противном случае операнды будут интерпретироваться как целые числа и результат также будет целочисленным. Обратите внимание, что это НЕ меняет типы самих операндов; меняется только то, как они вычисляются и сам тип выражения.
<?php
$foo = "0"; // $foo это строка (ASCII 48)
$foo += 2; // $foo теперь целое число (2)
$foo = $foo + 1.3; // $foo теперь число с плавающей точкой (3.3)
$foo = 5 + "10 Little Piggies"; // $foo это целое число (15)
$foo = 5 + "10 Small Pigs"; // $foo это целое число (15)
?>
Если последние два примера вам непонятны, смотрите Преобразование строк в числа.
Если вы хотите, чтобы переменная принудительно вычислялась как определенный тип, смотрите раздел приведение типов. Если вы хотите изменить тип переменной, смотрите settype().
Если вы хотите протестировать любой из примеров, приведенных в данном разделе, вы можете использовать функцию var_dump().
Замечание:
Поведение автоматического преобразования в массив в настоящий момент не определено.
К тому же, так как PHP поддерживает индексирование в строках аналогично смещениям элементов массивов, следующий пример будет верен для всех версий PHP:
<?php
$a = 'car'; // $a - это строка
$a[0] = 'b'; // $a все еще строка
echo $a; // bar
?>Более подробно смотрите в разделе Доступ к символу в строке.
Приведение типов
Приведение типов в PHP работает так же, как и в C: имя требуемого типа записывается в круглых скобках перед приводимой переменной.
<?php
$foo = 10; // $foo это целое число
$bar = (boolean) $foo; // $bar это булев тип
?>
Допускаются следующие приведения типов:
- (int), (integer) - приведение к integer
- (bool), (boolean) - приведение к boolean
- (float), (double), (real) - приведение к float
- (string) - приведение к string
- (array) - приведение к array
- (object) - приведение к object
- (unset) - приведение к NULL (PHP 5)
Приведение типа (binary) и поддержка префикса b были добавлены в PHP 5.2.1
Обратите внимание, что внутри скобок допускаются пробелы и символы табуляции, поэтому следующие примеры равносильны по своему действию:
<?php
$foo = (int) $bar;
$foo = ( int ) $bar;
?>
Приведение строковых литералов и переменных к бинарным строкам:
<?php
$binary = (binary) $string;
$binary = b"binary string";
?>
Замечание:
Вместо использования приведения переменной к string, можно также заключить ее в двойные кавычки.
<?php
$foo = 10; // $foo - это целое число
$str = "$foo"; // $str - это строка
$fst = (string) $foo; // $fst - это тоже строка
// Это напечатает "они одинаковы"
if ($fst === $str) {
echo "они одинаковы";
}
?>
Может быть не совсем ясно, что именно происходит при приведении между типами. Для дополнительной информации смотрите разделы:
Коментарии
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!
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
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;
}
}
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;
?>
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.
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].
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
?>