Класс ArrayObject

(PHP 5, PHP 7)

Введение

Данный класс позволяет работать с объектами как с массивами.

Обзор классов

ArrayObject implements IteratorAggregate , ArrayAccess , Serializable , Countable {
/* Константы */
const integer STD_PROP_LIST = 1 ;
const integer ARRAY_AS_PROPS = 2 ;
/* Методы */
public __construct ([ mixed $input = [] [, int $flags = 0 [, string $iterator_class = "ArrayIterator" ]]] )
public void append ( mixed $value )
public void asort ( void )
public int count ( void )
public array exchangeArray ( mixed $input )
public array getArrayCopy ( void )
public int getFlags ( void )
public ArrayIterator getIterator ( void )
public string getIteratorClass ( void )
public void ksort ( void )
public void natcasesort ( void )
public void natsort ( void )
public bool offsetExists ( mixed $index )
public mixed offsetGet ( mixed $index )
public void offsetSet ( mixed $index , mixed $newval )
public void offsetUnset ( mixed $index )
public string serialize ( void )
public void setFlags ( int $flags )
public void setIteratorClass ( string $iterator_class )
public void uasort ( callable $cmp_function )
public void uksort ( callable $cmp_function )
public void unserialize ( string $serialized )
}

Предопределенные константы

Опции ArrayObject

ArrayObject::STD_PROP_LIST

Свойства объекта получают стандартное поведение, при доступе к объекту как к списку (var_dump, foreach и т.д.).

ArrayObject::ARRAY_AS_PROPS

Записи могут быть доступны как свойства (для чтения и записи).

Список изменений

Версия Описание
5.3.0 Реализует Serializable.

Содержание

Коментарии

Автор:
Too bad the Array functions [1] are not available on this object… otherwise I would be using it all the time.

[1] http://nl.php.net/manual/en/ref.array.php
2008-08-09 21:17:58
http://php5.kiev.ua/manual/ru/class.arrayobject.html
If you want to use array functions on an ArrayObject, why not use iterator_to_array() to get a standard PHP array?  Do your operations on that array, then instantiate a new ArrayObject, passing it the array.

This might be a little slow on large ArrayObjects, but you'd have access to all of the array functions.
2008-09-05 11:28:29
http://php5.kiev.ua/manual/ru/class.arrayobject.html
Автор:
Simple example of usage : 

<?php

$array 
= array('Buck','Jerry','Tomas');

$arrayObject = new ArrayObject($array);
// Add new element
$arrayObject->append('Tweety');

// We are getting the iterator of the object
$iterator $arrayObject->getIterator();

// Simple while loop
while ($iterator->valid()) {
    echo 
$iterator->current() . "\n";
   
$iterator->next();
}

/* Outputs */
Buck
Jerry
Tomas
Tweety

?>

Note that not all the public methods of this class are documented here .
( Which includes a lot sorting methods ) .

Regards
2008-11-05 03:09:09
http://php5.kiev.ua/manual/ru/class.arrayobject.html
Generally variable $this can't be used as an array within an object context. For example, following code piece would cause a fatal error:

<?php
class TestThis {
    public function 
__set($name$val) {
       
$this[$name] = $val;
    }

    public function 
__get($name) {
        return 
$this[$name];
    }
}

$obj = new TestThis();
$obj->'aaa';
echo 
$obj->"\n";
?>

But things are different when $this is used in an ArrayObject object. e.g., following code piece are valid:

<?php
class TestArrayObject extends ArrayObject {   
    public function 
__set($name$val) {
       
$this[$name] = $val;
    }

    public function 
__get($name) {
        return 
$this[$name];
    }
}

$obj = new TestArrayObject();
$obj->'aaa';
echo 
$obj->"\n";
?>
2009-01-02 15:31:50
http://php5.kiev.ua/manual/ru/class.arrayobject.html
According to my benchmarks, doing foreach() on an ArrayObject is significantly slower than doing so on a vanilla array(). However, inserting keys and retrieving them is almost the same speed.

So, if performance is important, consider not using ArrayObject or descendant classes when you're iterating over its values a lot.

These are my timing results, using PEAR::Benchmark:

ArrayObject fill            0.01441502571106   
ArrayObject read_key        0.018320083618164   
ArrayObject read_foreach    2.1559031009674   

array() fill                0.012364864349365   
array() read_key            0.013092041015625   
array() read_foreach        0.011217832565308   

In all cases, 'fill()' inserts 10000 numbers at string keys, 'read_key()' reads all of those values by referencing the keys, and 'read_foreach()' does the same by walking through the array(object) with foreach().

As you can see, filling or reading from an ArrayObject by key is only 10% to 15% slower, but doing a foreach() is 200 times as costly. I am not sure what the cause of this may be.
2009-04-18 06:25:50
http://php5.kiev.ua/manual/ru/class.arrayobject.html
To implement array-style appending (e.g. "$object[] = 'foo';") in your own class implementing the ArrayAccess _interface_, all you need do is check if the key passed to your implementation of offsetSet() is NULL.  Something like the following.

<?php

class MyArrayObject implements ArrayAccess {

   
/**
     * @var array
     */
   
private $aValue;

   
// ...

    /**
     * @see ArrayAccess::offsetSet()
     */
   
public function offsetSet ($p_key$p_value) {
        if (
is_null($p_key)) {
           
$this->aValue[] = $p_value;
        }
        else {
           
$this->aValue[$p_key] = $p_value;
        }
    }

   
// ...
}
?>
2009-08-23 11:56:41
http://php5.kiev.ua/manual/ru/class.arrayobject.html
I don't believe the same performance is true since PHP 5.3. Using the same fill, read_key and foreach approach on both native arrays and ArrayObjects with 10000 keys I get the following

PHP 5.2

array() fill         0.013101
array() read         0.008685
array() foreach      0.004319
ArrayObject fill     0.014136
ArrayObject read     0.010003
ArrayObject foreach  3.454612

PHP 5.3

array() fill         0.010395
array() read         0.005933
array() foreach      0.001903
ArrayObject fill     0.010598
ArrayObject read     0.006387
ArrayObject foreach  0.003451

This was the code I used for both, an array or ArrayObject is passed into each of the functions. Again PEAR::Benchmark was used to get the results.

<?php
require_once 'Benchmark/Timer.php';

define('KEYS'10000);

function 
fill(&$arr) {
    for (
$i 1$i <= KEYS$i++) {
       
$arr['key-' $i] = $i;
    }
}

function 
read_key(&$arr) {
    for (
$i 1$i <= KEYS$i++) {
       
$v $arr['key-' $i];
    }
}

function 
fe(&$arr) {
    foreach (
$arr as $key => $value) {
       
$v $value;
    }
}
?>
2011-03-03 06:38:16
http://php5.kiev.ua/manual/ru/class.arrayobject.html
If you plan to derive your own class from ArrayObject, and  wish to maintain complete ArrayObject functionality (such as being able to cast to an array), it is necessary to use ArrayObject's own private property "storage".

Since that is impossible to do directly, you must use ArrayObject's offset{Set,Get,Exists,Unset} methods to manipulate it indirectly.

As a side benefit, this means you inherit all the iteration and other functions in complete working order.

This may sound obvious to someone who has never implemented their own ArrayObject class...  but it is far from so.

<?php

class MyArrayObject extends ArrayObject {
        static 
$debugLevel 2;

        static public function 
sdprintf() {
                if (static::
$debugLevel 1) {
                       
call_user_func_array("printf"func_get_args());
                }
        }

        public function 
offsetGet($name) { 
               
self::sdprintf("%s(%s)\n"__FUNCTION__implode(","func_get_args()));
                return 
call_user_func_array(array(parent__FUNCTION__), func_get_args());
        }
        public function 
offsetSet($name$value) { 
               
self::sdprintf("%s(%s)\n"__FUNCTION__implode(","func_get_args()));
                return 
call_user_func_array(array(parent__FUNCTION__), func_get_args());
        }
        public function 
offsetExists($name) { 
               
self::sdprintf("%s(%s)\n"__FUNCTION__implode(","func_get_args()));
                return 
call_user_func_array(array(parent__FUNCTION__), func_get_args());
        }
        public function 
offsetUnset($name) { 
               
self::sdprintf("%s(%s)\n"__FUNCTION__implode(","func_get_args()));
                return 
call_user_func_array(array(parent__FUNCTION__), func_get_args());
        }
}

$mao = new MyArrayObject();
$mao["name"] = "bob";
$mao["friend"] = "jane";
print_r((array)$mao);

/* Output:
 
offsetSet(name,bob)
offsetSet(friend,jane)
Array
(
    [name] => bob
    [friend] => jane
)       */
?>

If you wish to use the "Array as Properties" flag, you simply need to include this in your constructor: 

<?php parent::setFlags(parent::ARRAY_AS_PROPS); ?>

This will allow you to do things such as the below example, without overriding __get or __set .

<?php
$mao
->name "Phil";
echo 
$mao["name"];   /* Outputs "Phil" */
?>
2011-04-17 03:27:35
http://php5.kiev.ua/manual/ru/class.arrayobject.html
A gotcha that is indeed mentioned in the manual, but isn't readily obvious and just cost me half an hour:

Objects implementing the Serializable interface do NOT get __sleep and __wakeup called; instead, they use serialize and unserialize methods, respectively (why, I don't know, but whatever - I'm sure there's a reason).

Hence, I was trying to serialize a database resultset in an object extending ArrayObject, and needed to fix some stuff regarding database resources on serialize. Took me a while to figure out __sleep wasn't getting called because ArrayObjects implements Serialize...

Presumably the ArrayObject internally implements the serialize/unserialize methods (in a trivial manner), hence the error wasn't apparent immediately (i.e., no fatal error was thrown) and I'd been trying to track why my objects didn't get serialized (they were of course) instead of renaming and fixing the methods.
2011-07-21 15:34:53
http://php5.kiev.ua/manual/ru/class.arrayobject.html
I found the description of STD_PROP_LIST a bit vague, so I put together a simple demonstration to show its behavior:

<?php                                                     
                                                         
$a 
= new ArrayObject(array(), ArrayObject::STD_PROP_LIST);
   
$a['arr'] = 'array data';                             
   
$a->prop 'prop data';                               
$b = new ArrayObject();                                   
   
$b['arr'] = 'array data';                             
   
$b->prop 'prop data';                               
                                                         
// ArrayObject Object                                     
// (                                                     
//      [prop] => prop data                               
// )                                                     
print_r($a);                                             
                                                         
// ArrayObject Object                                     
// (                                                     
//      [arr] => array data                               
// )                                                     
print_r($b);                                             
                                                         
?>
2011-08-21 21:05:28
http://php5.kiev.ua/manual/ru/class.arrayobject.html
As you know ArrayObject is not an array so you can't use the built in array functions. Here's a trick around that:

Extend the ArrayObject class with your own and implement this magic method:

<?php
   
public function __call($func$argv)
    {
        if (!
is_callable($func) || substr($func06) !== 'array_')
        {
            throw new 
BadMethodCallException(__CLASS__.'->'.$func);
        }
        return 
call_user_func_array($funcarray_merge(array($this->getArrayCopy()), $argv));
    }
?>

Now you can do this with any array_* function:
<?php
$yourObject
->array_keys();
?>
- Don't forget to ommit the first parameter - it's automatic!

Note: You might want to write your own functions if you're working with large sets of data.
2012-01-05 10:24:37
http://php5.kiev.ua/manual/ru/class.arrayobject.html
Автор:
Long story short b/c arrays by default are passed by value, if you pass an array to a function, the function works on a copy of the array while the original array remains unaltered by the function.

You may cause a change to the array to be reflected in the original array by having the function return the altered array and assign it to the variable for the original array, as follows:

<?php
function my_array_modify($data) { 
   
$data['b'] = 2;
    return 
$data;     


$regularArray = array(); 

$regularArray['a'] = 1
 
$regularArray my_array_modify($regularArray); 

var_dump($regularArray['b']); // 2 
?>

Or, you may explicitly pass the array by reference in which case there is no need for the function to return the array since the change will have effected the original array, as follows:

<?php
function my_arrayref_modify(&$data) { 
   
$data['bb'] = 22;

my_arrayref_modify($regularArray);
var_dump($regularArray['bb']); // 22
?>
2012-11-07 00:28:33
http://php5.kiev.ua/manual/ru/class.arrayobject.html
There is a better explanation about the ArrayObject flags (STD_PROP_LIST and ARRAY_AS_PROPS) right here: 

http://stackoverflow.com/a/16619183/1019305

Thanks to JayTaph
2013-08-12 00:30:00
http://php5.kiev.ua/manual/ru/class.arrayobject.html
Автор:
// Example STD_PROP_LIST and ARRAY_AS_PROP combined
<?php
$ao 
= new ArrayObject();
$ao ->setFlags(ArrayObject::STD_PROP_LIST|ArrayObject::ARRAY_AS_PROPS);

$ao->prop 'prop data';
$ao['arr'] = 'array data';

print_r($ao);

?>

// Result

ArrayObject Object
(
    [storage:ArrayObject:private] =&gt; Array
        (
            [prop] => prop data
            [arr] => array data
        )

)
2014-11-17 15:51:06
http://php5.kiev.ua/manual/ru/class.arrayobject.html
Автор:
<?php
class Prototype extends ArrayObject
{
    private 
$___class null;
   
    public function 
__get($key)
    {
        return 
$this[$key];
    }

    public function 
__set($key$value)
    {
       
$this[$key] =  $value;
    }
   
    public function 
__call($key$args)
    {
        if(
is_object($this->___class) && is_callable([$this->___class$key])){
            return 
call_user_func_array([$this->___class$key],$args);
        }
        return 
is_callable($c $this->__get($key)) ? call_user_func_array($c$args) : null;
    }

    public function 
importObj($class$array = []){
       
$this->___class $class;
        if(
count($array) > 0){
           
$this->import($array);
        }
        return 
$this;
    }

    public function 
import($input)
    {
       
$this->exchangeArray($input);
        return 
$this;
    }

    public function 
export()
    {
        return 
$this->objectToArray($this->getArrayCopy());
    }

    public function 
objectToArray ($object) {
       
$o = [];
        foreach (
$object as $key => $value) {
           
$o[$key] = is_object($value) ? (array) $value$value;
        }
        return 
$o;
    }

}

class 
user{
    public 
$name 'Mahmoud Elnezamy';
    public function 
getName(){
        return 
'You Name is ' $this->name;
    }
}

//usage you can import object with some array

$add = ['age' => '27''country' => 'Egypt'];
$user = new user;
$Prototype = new Prototype;
$Prototype->importObj($user$add);
//print_r($Prototype);

echo $Prototype->getName().' ';
echo 
$Prototype->age.' ';
echo 
$Prototype->country;
2016-02-19 15:36:50
http://php5.kiev.ua/manual/ru/class.arrayobject.html
Автор:
If you want numerical ArrayObject objects to play nice with json_encode(), implement JsonSerializable:

class JsonSerializableArrayObject extends ArrayObject implements JsonSerializable {
    function jsonSerialize() {
        return $this->getArrayCopy();
    }
}

For assoc ArrayObject objects this isn't neccesary, but for numerical arrays it is, otherwise they will be formatted like

{"0":"jaap","1":"karel"}

instead of

["jaap","karel"]
2018-02-26 04:08:18
http://php5.kiev.ua/manual/ru/class.arrayobject.html
Автор:
You can easily realise that ArrayObject can use various functions as they are in ArrayIterator to iterate an object-as-a-array. However, you need to "activate" these function (rewind, valid, next and so on...) by using getIterator() first. Actually this function inherits from Iterator Aggregate interface.

Take a look at the following basic example. The results are the same:

<?php

$array 
= [1234];
$a = new ArrayObject($array);
$b = new ArrayIterator($array);

$iterator $a->getIterator();

for(
$iterator->rewind(); $iterator->valid(); $iterator->next()){
    echo 
$iterator->current()*2;
   
}

for(
$b->rewind(); $b->valid(); $b->next()){
    echo 
$b->current()*2
   
}

//Resulst are the same 2468 AND 2468
2018-05-08 18:52:43
http://php5.kiev.ua/manual/ru/class.arrayobject.html
class RecursiveArrayObject extends \ArrayObject
{
    public function __construct($input = array())
    {
        $data = array();
        foreach ($input as $key => $value) {
            if (is_array($value)) {
                $value = new self($value);
            }
            $data[$key] = $value;
        }
        parent::__construct($data, \ArrayObject::ARRAY_AS_PROPS);
    }
}

$company = new RecursiveArrayObject(array(
    'ceo' => array(
        'id' => 1,
        'name' => 'tony',
        'age' => 36
    ),
    'coo' => array(
        'id' => 2,
        'name' => 'matt',
        'age' => 35
    ),
    'cto' => array(
        'id' => 3,
        'name' => 'james',
        'age' => 35
    )
));

var_dump($company->cto->name); // string(5) "james"
var_dump($company['coo']['name']); // string(4) "matt"
2019-01-31 09:28:12
http://php5.kiev.ua/manual/ru/class.arrayobject.html
function map_of_array(array $element, $callable)
{
    foreach ($element as $key => $value) {
        $callable($key, $value);
    }
}

Usage: 

$key_values = ["name" => "krisna", "level" => 10];

map_of_array($key_values, function ($key, $value) {
      echo "\n", $key, "=", $value;
});

Result:

name=krisna
level=10
2020-05-05 05:59:28
http://php5.kiev.ua/manual/ru/class.arrayobject.html
If you want to use built-in array function with ArrayObject, store the iterator instance and return the value as reference in offsetGet.

<?php
class Collection extends \ArrayObject {
    public function 
__construct(array $data = [])
    {
        if (!
\is_array($data) && !\array_key_exists('ArrayAccess'class_implements($data))) {
           
$data = [$data];
        }

       
$this->iterator $this->getIterator();
       
parent::__construct($data);
    }

    public function &
offsetGet($index)
    {
       
$value = &$this->iterator[$index] ?? null;

        return 
$value;
    }
}
?>
2021-02-22 03:38:44
http://php5.kiev.ua/manual/ru/class.arrayobject.html
Differences between STD_PROP_LIST and ARRAY_AS_PROPS

<?php
$a 
= new ArrayObject([], ArrayObject::STD_PROP_LIST);
$a['arr'] = 'Array data';
$a->prop 'Prop data';

$b = new ArrayObject([], ArrayObject::ARRAY_AS_PROPS);
$b['arr'] = 'Array data';
$b->prop 'Prop data';

print_r($a);
/* Output

ArrayObject Object
(
    [prop] => Prop data
    [storage:ArrayObject:private] => Array
        (
            [arr] => Array data
        )

)*/

print_r($b);
/* Output

ArrayObject Object
(
    [storage:ArrayObject:private] => Array
        (
            [arr] => Array data
            [prop] => Prop data
        )

)*/

?>
2021-04-26 15:31:46
http://php5.kiev.ua/manual/ru/class.arrayobject.html
If you need the last key of your collection use:
<?php
array_key_last
($this->getArrayCopy())
?>

In an extending class it could look like:
<?php
class Collection extends ArrayObject
{
    public function 
lastKey(): int
   
{
        return 
array_key_last($this->getArrayCopy());
    }
}
?>

If you want to use any type safe collection:
<?php
class BookCollection extends Collection
{
    public function 
add(Book $book) : void
   
{
       
$this->offsetSet($book->id$book);
    }

   
// note the return type "Book"
   
public function get(int $bookId) : Book 
   
{
       
$this->offsetGet($bookId);
    }
}
?>
2022-01-30 03:07:37
http://php5.kiev.ua/manual/ru/class.arrayobject.html
Note that this does not truly "allow objects to work as arrays" - an `ArrayObject` will not type-check as an array:

<?php

function gimme(array $a) {
   
var_dump($a);
}

$a = new ArrayObject([1,2,3]);

var_dump(is_array($a)); // false

gimme($a); // Uncaught TypeError: gimme(): Argument #1 ($a) must be of type array, ArrayObject given

?>

If you want something that type-checks both for arrays and `ArrayObject`, use the `iterable` pseudotype instead:

<?php

function gimme(iterable $a) {
   
var_dump($a);
}

$a = [1,2,3];

var_dump(is_iterable($a)); // true

var_dump($a instanceof iterable); // false (iterable is a pseudo-type and cannot be type-checked using instanceof)

gimme($a); // works

gimme(new ArrayObject($a)); // works

?>

Notice the caveat here, that arrays will not type-check as `instanceof iterable`, because pseudotypes cannot be checked that way - if you need a run-time type-check, use `is_iterable` for the type-check instead.
2023-12-09 11:25:41
http://php5.kiev.ua/manual/ru/class.arrayobject.html

    Поддержать сайт на родительском проекте КГБ