Mastering the (array) Cast Operator in PHP: A Comprehensive Guide
PHP provides various tools and features to manipulate data efficiently. One such feature is the (array)
cast operator, which transform data into an array. In this blog post, we are mastering the (array)
cast operator in PHP, focusing on its applications with simple scalars, objects, arrays, recursive data and method call syntax.
- Basic usage of (array)
- Converting Simple values
- Converting Arrays to Array
- Converting Objects to Array
- Recursive Conversion To Array
- Converting Null To Array
- The Hidden Cast To Array
The Basics of (array) Cast Operator
The (array) cast operator is a simple and convenient way to convert different data types into an array. It is especially useful when working with data that are not yet in array format, whether you’re dealing with scalar values, objects, or other arrays.
Converting Simple Scalars To Array
Let’s start with the most basic use case, converting simple scalars like an integer, a string, a float into an array.
<?php $value = 8; $array = (array) $value; print_r($array);
In this case, the resulting array contains the original scalar value as the only element. So, if you cast an integer, you’ll get an array with one element containing that value. The same principle applies to a string and floats.
Converting Array To Array
These basic conversions are quite straightforward. Basically, there is no conversion of type, rather PHP creates an array and puts the value into that array, at the index 0.
So, obviously, one might wonder what happens when an array is cast to array, with (array)
. Well, nothing happens: the original array stays an array. It is an idempotent operator, for arrays.
<?php $value = [8]; $array = (array) $value; print_r($array); // [8] $array = (array) $value; print_r($array); // [8]
Converting Array To Multidimensional Array
If you want to nest an array inside another array, the (array)
is not a good tool. You need to make an explicit array creation, and put the original array in it.
<?php $value = [8]; $array = [$value]; print_r($array); // [[8]]
Converting Objects To Array
(array)
is able to convert objects to arrays. Each property of the array is converted to an index of the new array. The value is used without change. Constants and methods are dropped. Trait properties are included, and static properties are excluded.
<?php trait t { public $propertyT = 2; } class x extends stdClass { use t; static $static = 3; public $property = 1 } $object = new x; $object->otherObject = new stdClass; $object->otherObject->property2 = 2; $array = (array) $object; print_r($array); /* Array ( [propertyT] => 2 [property] => 1 [otherObject] => stdClass Object ( [property2] => 2 ) ) */
The conversion is based on the object, and not on the class. The nuance is that dynamically assigned properties are included, and unset properties are omitted. This wouldn’t be the case with property_exists(), which uses the class definition.
Also, note that the object on otherObject
property stays as an object. It is not recursively turned into another array.
Converting Non-Visible Properties To Array
(array)
takes into account the visibility of the properties when converting an object to an array. Protected and private properties are included in the case, yet they get a special treatment.
<?php class x extends stdClass { public $public = 1; protected $protected = 2; private $private = 3; } $object = new x; $array = (array) $object; print_r($array); /* Array ( [public] => 1 [*protected] => 2 [xprivate] => 3 ) */
As you can see, protected properties get an asterisk *
before them, and private properties get the name of the class.
In fact, there is more than the eye can see: quite literally. The names of the non-public properties have a special format, which cannot be displayed when called with print_r() nor with a foreach() loop.
The protected properties are prefixed with an asterisk, framed with two NUL characters (the ASCII one) : chr(0)*chr(0)
. The private properties use the actual name of the class between two NUL characters.
This means that it requires a few extra steps to reach those entries in the new array.
<?php class x extends stdClass { public $public = 1; protected $protected = 2; private $private = 3; } $object = new x; $array = (array) $object; print_r($array['*protected']); // Undefined array key "*protected" print_r($array['xprivate']); // Undefined array key "xprivate" print_r($array[chr(0).'*'.chr(0).'protected']); // 2 print_r($array[chr(0).'x'.chr(0).''private']); // 3
Recursive Conversion To Array
(array)
is not recursive. When come the time to convert an object to an array, any recursion has to be handled manually.
A trick is to use the json_decode()
method. The second argument of this function tells PHP to automatically convert a JSON object to a PHP array.
Hence, to recursively convert an object to an array, once can use the JSON functions that way:
<?php $object = new stdClass; $object->property = 1; $object->otherObject = new stdClass; $object->otherObject->property2 = 2; $array = json_decode(json_encode($object), associative: true); print_r($array); /* Array ( [property] => 1 [otherObject] => Array ( [property2] => 2 ) ) */
Converting Null to an array
Now, we’ll go back to a special case: null
. This value, or, to be precise, the absence of data, is converted to an empty array, with the operator (array)
.
<?php $null = null; $array = (array) $null; print_r($array); // [] ?>
Instead of setting the value in an array, PHP converts null
to the empty array(). Technically, it is an array with nothing in it, just like null
represents nothing.
If you need that value to be stored in an array, then you need to put it manually in the array, like for nesting arrays in arrays.
The hidden cast to array
One of the reason to cast values to array is to handle all elements of a list of objects in the same way, may they be zero, one or more. The downside of writing all these lists as an array, is that it creates a lot of syntax overhead to put them in a literal array.
It looks really weird when there is only one element. And developers always favor a short syntax.
Here is an example of a function that process some strings. The payload is not important here. Look at the calls and signature.
<?php foo('a'); foo(array('a')); function foo(string|array $values) { if (is_string($values)) { $values = [$values]; } foreach($values as $value) { doSomething($value); } } ?>
First, we can simplify this code with what we know of the (array)
operator: it is idempotent.
<?php foo('a'); foo(array('a')); function foo(string|array $values) { $values = (array) $values; foreach($values as $value) { doSomething($value); } } ?>
The second trick is to hide all this code in the signature of the function, with the ...
operator. It is used in a method signature to indicate that the method can accept a variable number of arguments. This operator is often used when a method can accept any number of arguments without having to specify each argument individually.
<?php foo('a'); foo('a', 'b', 'c'); foo(...$array); function foo(string ...$values) { foreach($values as $value) { doSomething($value); } } ?>
When no argument is provided, the parameter $values
is an empty array. Checkout out for compulsory arguments, as this means the method may be called without any argument, and still run.
Cherry on the sundae, the type system still works. Each of the arguments is checked for the same type (here, string). This is an added bonus, and there is no need to do it again inside the method. In fact, such checks were not done in our initial version of the function. It was only done for single arguments, and yet, not well enough.
<?php // No argument => empty $values foo(); // One argument => it is set in an array foo('a'); // Several argument => they are set in an array foo('a', 'b', 'c', ... ); // Several argument already set in an array foo(...$array); // Type system kicks in and prevents this call foo(['a']); function foo(string ...$values) { foreach($values as $value) { doSomething($value); } } ?>
Conclusion
Mastering the (array)
cast operator in PHP is a be powerful tool in your data manipulation toolkit. This operator provides the flexibility to convert various data types into arrays, in an ad hoc manner, making it a versatile manipulating collections of elements.