Typumwandlung (Typen-Jonglage)

PHP verlangt in der Variablendeklaration keine explizite Typdefinition. Der Typ einer Variablen wird in diesem Fall durch den Wert bestimmt, der in ihr gespeichert wird. Das heißt, wenn der Variable $var der Typ string zugewiesen wird, dann ist $var vom Typ string. Wenn $var anschließend ein Wert vom Typ int zugewiesen wird, ist sie vom Typ int.

PHP kann je nach Kontext versuchen, den Typ eines Wertes automatisch in einen anderen umzuwandeln. Folgende Kontexte gibt es:

  • Numerisch
  • Zeichenkette
  • Logisch
  • Ganzzahlig und Zeichenkette
  • Vergleichend
  • Funktion

Hinweis: Wenn ein Wert als ein anderer Typ interpretiert werden muss, wird der Typ des Wertes selbst nicht geändert.

Um zu erzwingen, dass eine Variable als ein bestimmter Typ ausgewertet wird, siehe den Abschnitt über Explizite Typumwandlung (Type-Casting). Um den Typ einer Variablen zu ändern, siehe die Funktion settype().

Numerischer Kontext

Dieser Kontext liegt vor, wenn ein arithmetischer Operator verwendet wird.

Wenn in diesem Kontext einer der beiden Operanden vom Typ float ist (oder nicht als Int interpretiert werden kann), werden beide Operanden als Floats interpretiert, und das Ergebnis ist vom Typ float. Andernfalls werden die Operanden als Ints interpretiert, und das Ergebnis ist ebenfalls vom Typ int. Wenn einer der Operanden nicht interpretiert werden kann, wird seit PHP 8.0.0 ein TypeError geworfen.

Zeichenketten-Kontext

Dieser Kontext liegt vor, wenn echo, print, Zeichenketten-Interpolation, oder der Verkettungsoperator für Zeichenketten verwendet werden.

In diesem Kontext wird der Wert als String interpretiert. Wenn der Wert nicht interpretiert werden kann, wird ein TypeError geworfen. Vor PHP 7.4.0 wurde ein E_RECOVERABLE_ERROR ausgelöst.

Logischer Kontext

Dieser Kontext liegt vor, wenn bedingte Anweisungen, der ternäre Operator oder ein logischer Operator verwendet werden.

In diesem Kontext wird der Wert als Bool interpretiert.

Kontext für ganzzahlige Werte und Zeichenketten

Dieser Kontext liegt vor, wenn bitweise Operatoren verwendet werden.

Wenn in diesem Kontext alle Operanden vom Typ string sind, ist auch das Ergebnis vom Typ string. Andernfalls werden die Operanden als Ints interpretiert, und das Ergebnis ist ebenfalls vom Typ int. Wenn einer der Operanden nicht interpretiert werden kann, wird seit PHP 8.0.0 ein TypeError geworfen.

Vergleichender Kontext

Dieser Kontext liegt vor, wenn ein Vergleichsoperator verwendet wird.

Die in diesem Zusammenhang auftretenden Typumwandlungen werden in der Tabelle Vergleich mit verschiedenen Typen erläutert.

Funktionskontext

Dieser Kontext liegt vor, wenn ein Wert an einen typisierten Parameter oder eine Eigenschaft übergeben oder von einer Funktion zurückgegeben wird, die einen Rückgabetyp deklariert.

In diesem Kontext muss der Wert ein Wert dieses Typs sein. Hiervon gibt es zwei Ausnahmen. Die Erste: Wenn der Wert vom Typ int ist und der deklarierte Typ ist float, dann wird die Ganzzahl in eine Gleitkommazahl umgewandelt. Die Zweite: Wenn der deklarierte Typ ein skalarer Typ ist, der Wert in einen skalaren Typ umgewandelt werden kann und der Modus der zwangsweisen Typisierung aktiv ist (Standard), kann der Wert in einen akzeptierten skalaren Wert umgewandelt werden. Siehe unten für eine Beschreibung dieses Verhaltens.

Warnung

Interne Funktionen wandeln null automatisch in skalare Typen um. Dieses Verhalten ist seit PHP 8.1.0 DEPRECATED (veraltet).

Automatische Typisierung mit einfachen Typdeklarationen

  • Deklaration des Typs bool: Der Wert wird als bool interpretiert.
  • Deklaration des Typs int: Der Wert wird als int interpretiert, wenn die Umwandlung wohldefiniert ist, z. B. wenn die Zeichenkette numerisch ist.
  • Deklaration des Typs float: Der Wert wird als float interpretiert, wenn die Umwandlung wohldefiniert ist, z. B. wenn die Zeichenkette numerisch ist.
  • Deklaration des Typs string: Der Wert wird als string interpretiert.

Automatische Typisierung mit Union-Typen

Wenn strict_types nicht aktiviert ist, unterliegen skalare Typdeklarationen einer begrenzten impliziten Typumwandlung. Wenn der genaue Typ des Wertes nicht Teil der Union ist, wird der Zieltyp in der folgenden Reihenfolge gewählt:

  1. int
  2. float
  3. string
  4. bool
Wenn der Typ in der Union existiert und der Wert gemäß der PHP-Semantik zur Typüberprüfung in diesen Typ umgewandelt werden kann, wird dieser Typ ausgewählt. Andernfalls wird der nächste Typ geprüft.

Achtung

Wenn es sich bei dem Wert um eine Zeichenkette handelt und sowohl int als auch float Teil der Union sind, wird der bevorzugte Typ durch die bestehende Semantik numerischer Zeichenketten bestimmt. Zum Beispiel wird für "42" int gewählt, während für "42.0" float gewählt wird.

Hinweis:

Typen, die nicht in der obigen Präferenzliste aufgeführt sind, kommen als Ziele für implizite Umwandlungen nicht in Frage. Insbesondere gibt es keine impliziten Umwandlungen in die Typen null, false und true.

Beispiel #1 Beispiel für Typen, die in einen Typ umgewandelt werden, der Teil einer Union ist

<?php
// int|string
42 --> 42 // exakter Typ
"42" --> "42" // exakter Typ
new ObjectWithToString --> "Result of __toString()"
// object nicht kompatibel mit int, greift auf string zurück
42.0 --> 42 // float kompatibel mit int
42.1 --> 42 // float kompatibel mit int
1e100 --> "1.0E+100" // float zu groß für Typ int, greift auf string zurück
INF --> "INF" // float zu groß für Typ int, greift auf string zurück
true --> 1 // bool kompatibel mit int
[] --> TypeError // array nicht kompatibel mit int oder string

// int|float|bool
"45" --> 45 // Zeichenkette im numerischen Format für int
"45.0" --> 45.0 // Zeichenkette im numerischen Format für float

"45X" --> true // keine numerische Zeichenkette, greift auf bool zurück
"" --> false // keine numerische Zeichenkette, greift auf bool zurück
"X" --> true // keine numerische Zeichenkette, greift auf bool zurück
[] --> TypeError // array nicht kompatibel mit int, float oder bool
?>

Explizite Typumwandlung (Type-Casting)

Typ-Casting wandelt den Wert in einen bestimmten Typ um, indem der Typ in Klammern vor den umzuwandelnden Wert geschrieben wird.

<?php
$foo
= 10; // $foo ist ein Integer
$bar = (bool) $foo; // $bar ist ein Boolean
?>

Folgende Umwandlungen sind erlaubt:

  • (int) - Umwandlung in int
  • (bool) - Umwandlung in bool
  • (float) - Umwandlung in float
  • (string) - Umwandlung in string
  • (array) - Umwandlung in array
  • (object) - Umwandlung in object
  • (unset) - Umwandlung in NULL

Hinweis:

(integer) ist ein Alias des (int)-Casts. (boolean) ist ein Alias des (bool)-Casts. (binary) ist ein Alias des (string)-Casts. (double) und (real) sind Aliase des (float)-Casts. Da diese Casts nicht den kanonischen Typnamen verwenden, werden sie nicht empfohlen.

Warnung

Der Cast-Alias (real) ist seit PHP 8.0.0 veraltet.

Warnung

Der (unset)-Cast ist seit PHP 7.2.0 veraltet und wurde in PHP 8.0.0 entfernt. Es ist zu beachten, dass der (unset)-Cast gleichbedeutend ist mit der Zuweisung des Wertes NULL an eine Variable oder einen Aufruf.

Achtung

Der (binary)-Cast und das Präfix b existieren im Hinblick auf zukünftige Versionen. Derzeit sind (binary) und (string) identisch, aber weil sich dies in Zukunft ändern könnte, sollte man sich nicht darauf verlassen.

Hinweis:

Leerzeichen werden innerhalb der Klammern eines Casts ignoriert, weshalb die beiden folgenden Ausdrücke gleichwertig sind:

<?php
$foo
= (int) $bar;
$foo = ( int ) $bar;
?>

Umwandlung literaler Strings und Variablen in binäre Strings:

<?php
$binary
= (binary) $string;
$binary = b"binary string";
?>

Hinweis: Anstatt eine Variable in einen String umzuwandeln, kann die Variable auch in doppelte Anführungszeichen gesetzt werden.

<?php
$foo
= 10; // $foo ist eine ganze Zahl
$str = "$foo"; // $str ist eine Zeichenkette
$fst = (string) $foo; // $fst ist ebenfalls eine Zeichenkette

// Dies gibt aus "sie sind identisch"
if ($fst === $str) {
echo
"sie sind identisch";
}
?>

In den folgenden Abschnitten wird beschrieben, was genau passiert, wenn zwischen bestimmten Typen umgewandelt wird:

Hinweis: Da Strings in PHP mit derselben Syntax wie Arrays über Offsets indiziert werden können, gilt das folgende Beispiel für alle PHP-Versionen:

<?php
$a
= 'car'; // $a ist eine Zeichenkette
$a[0] = 'b'; // $a ist immer noch eine Zeichenkette
echo $a; // bar
?>
Weitere Informationen sind im Abschnitt Zugriff auf Zeichen in einem String zu finden.

add a note

User Contributed Notes 7 notes

up
67
Raja
19 years ago
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
up
27
fardelian
11 years ago
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.
up
11
Anonymous
3 years ago
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].
up
13
miracle at 1oo-percent dot de
18 years ago
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)
up
12
rmirabelle
13 years ago
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;
}
}
up
18
Anonymous
21 years ago
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!
up
15
ieee at REMOVE dot bk dot ru
12 years ago
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;
?>
To Top