If i have an array represented in an ArrayObject like this:
$arrObj = new ArrayObject([
'foo' => 1,
'bar' => 2,
]);
Then I can comfortably cast it:
print_r((array)$array);
// output is as expected
But I cannot pass it as an argument that’s typed as an array:
function castTest(array $array)
{
}
castTest($arrObj);
// TypeError: castTest(): Argument #1 ($array) must be of type array, ArrayObject given
Is this intentional? Desirable? Are there any exceptions in PHP that CAN auto-cast objects to arrays?
It works with string objects, for example, with a __toString implemented:
class Str
{
private string $string;
public function __construct(string $string)
{
$this->string = $string;
}
public function __toString()
{
return $this->string;
}
}
function castTest(string $string)
{
echo $string;
}
$str = new Str('hello, world');
castTest($str); // outputs: hello, world
2
Answers
Yes this is intentional. The ArrayObject may behave like an array but isn’t actually an array. PHP enforces strict typing in function arguments. If an argument is defined as an array it only accepts arrays. The behaviour you observed with the
__toString
method is different because when an object is used in a string context the__toString
method is automaticaly called by PHP if it is defined. However, this behavior does not apply to arrays or other non-string types.You can convert an ArrayObject to an Array by using
getArrayCopy()
This is because it’s a different type and argument type checks are strict. An array is an
array
type. AnArrayObject
is and "object" type (though there is noObject
type, it is still a separate type of variable in PHP). This is also because PHP does not have scalar objects. They are objects that represent scalar values behind the scenes. For instance, if you create astring
variable, a language with scalar objects would instantiate aString
object transparently. This has been suggested to PHP a few times in the past, but not likely to get added soon.However, you can allow array objects to be passed along with arrays by altering the argument’s type restriction. PHP 8 introduced union types using the pipe character. You can allow objects able to be accessed like arrays through by adding the
ArrayAccess
interface:The
array|ArrayAccess
type restriction means "only allow variables of typearray
or of object typeArrayAccess
".If you are using an older version of PHP (7 or earlier), your two options are to cast the object to an array (remember that it will no longer be an object within the function, but a separate array entirely which may have implications depending on how the data is handled), or check for types within the function itself. Here are examples: