简体   繁体   中英

php Converting an object implementing ArrayAccess in array

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

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.

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 : ie 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.

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
    );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM