4

When you implement the _toString method on a class, you are able to convert the object in string

$string =(string) $object

Is there an equivalent for converting in array

$array=(array) $object

From what I have tested, with this code, the attributes of the objet are transformed in index of the array, even if this object implement ArrayAccess.

I expected that casting an object with array access, I would obtain an array thith the same values I could access with the object

public class MyObject implements ArrayAccess{
     private $values;
     public function __construct(array $values){
        $this->values=$values;
     }
     public function offsetSet($name,$value){
        $this->values[$name]=$value;
     }
     //etc...
}

$myObject=new MyObject(array('foo'=>'bar');

$asArray=(array)$myObject;

print_r($asArray);
// expect array('foo'=>'bar')
// but get array('MyObjectvalues'=>array('foo'=>'bar'));

I also Notice that the native ArrayObject class has a the behavior I expected

Arnaud
  • 41
  • 1
  • 2
  • Either derive from ArrayObject and reuse getArrayCopy; or reimplement it by just returning the $values prop. Casting won't work, as there's no `__toArray` handling. – mario Dec 02 '14 at 09:39
  • `public function MyObject implements ArrayAccess{` <-- this is not valid PHP syntax. You want `class MyObject implements ArrayAccess { ...`. – faintsignal Aug 22 '17 at 21:13

3 Answers3

4

No, there is no magic function to cast object as array.

ArrayObject is implemented with C and has weird specific behaviors.

Implement custom method asArray and use it.

sectus
  • 15,605
  • 5
  • 55
  • 97
1

Actually, it's impossible to write a general function:

/*
 * @return array ArrayAccess object converted into an array
 */
function (ArrayAccess $arrayAccessObject): array { /* ... */ }

Why? Because ArrayAccess interface just gives a way to use $aa[/*argument*/] syntax, but does not give a way to iterate over all possible arguments.

We used to think that array has a finite number of keys. However ArrayAccess let us create objects having an infinite set of keys (note, the same concerns Traversable: i.e. prime numbers are "traversable").

For example, one can write a class, implementing ArrayAccess, that acts like a HTTP client with a cache (I'm not saying that it's a good idea; it's just an example). Then offsetExists($url) tells if a URL gives 200 or not, offsetGet($url) returns a content of a URL, offsetUnset($url) clears cached content, offsetSet throws a LogicException, 'cause setting a value makes no sense in this context.

// ...
if (empty($client['https://example.com/file.csv'])) {
    throw new RuntimeException('Cannot download the file');
}
$content = $client['https://example.com/file.csv'];
// ...

Or maybe one wants to read/write/unset (delete) files with ArrayAccess.

Or maybe something like (set of even numbers is infinite):

$even = new EvenNumberChecker(); // EvenNumberChecker implements ArrayAccess
$even[2]; // true
$even[3]; // false
$even[5.6]; // throws UnexpectedValueException
isset($even[7.8]); // false
$even[0] = $value; // throws LogicException

ArrayAccess objects from academic examples above cannot be converted into finite arrays.

jacek.ciach
  • 904
  • 11
  • 20
0

You can use json_decode and json_encode to get the most generic function for it:

public static function toArray(ArrayAccess $array): array
{
    return json_decode(
        json_encode($array),
        true
    );
}
Ruslan D.
  • 441
  • 4
  • 4