(PHP 5, PHP 7, PHP 8)
IntroductionInterface to provide accessing objects as arrays.
Interface synopsisinterface ArrayAccess {
}
ExamplesExample #1 Basic usage
<?php
class Obj implements ArrayAccess {
public $container = [
"one" => 1,
"two" => 2,
"three" => 3,
];
public function
offsetSet($offset, $value): void {
if (is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
}
public function
offsetExists($offset): bool {
return isset($this->container[$offset]);
}
public function
offsetUnset($offset): void {
unset($this->container[$offset]);
}
public function
offsetGet($offset): mixed {
return isset($this->container[$offset]) ? $this->container[$offset] : null;
}
}$obj = new Obj;var_dump(isset($obj["two"]));
var_dump($obj["two"]);
unset($obj["two"]);
var_dump(isset($obj["two"]));
$obj["two"] = "A value";
var_dump($obj["two"]);
$obj[] = 'Append 1';
$obj[] = 'Append 2';
$obj[] = 'Append 3';
print_r($obj);
?>
The above example will output something similar to:
bool(true) int(2) bool(false) string(7) "A value" obj Object ( [container:obj:private] => Array ( [one] => 1 [three] => 3 [two] => A value [0] => Append 1 [1] => Append 2 [2] => Append 3 ) )Table of Contents
13 years ago
It bit me today, so putting it here in the hope it will help others:
If you call array_key_exists() on an object of a class that implements ArrayAccess, ArrayAccess::offsetExists() wil NOT be called.
11 years ago
<?phpclass ArrayAndObjectAccess implements ArrayAccess {private $data = [];public function &__get ($key) {
return $this->data[$key];
}public function __set($key,$value) {
$this->data[$key] = $value;
}public function __isset ($key) {
return isset($this->data[$key]);
}public function __unset($key) {
unset($this->data[$key]);
}public function offsetSet($offset,$value) {
if (is_null($offset)) {
$this->data[] = $value;
} else {
$this->data[$offset] = $value;
}
}public function offsetExists($offset) {
return isset($this->data[$offset]);
}public function offsetUnset($offset) {
if ($this->offsetExists($offset)) {
unset($this->data[$offset]);
}
}public function offsetGet($offset) {
return $this->offsetExists($offset) ? $this->data[$offset] : null;
}
}
?>
Usage
<?php
$foo = new ArrayAndObjectAccess();
$foo->fname = 'Yousef';
$foo->lname = 'Ismaeil';
echo 'fname as object '.$foo->fname."\n";
echo 'lname as array '.$foo['lname']."\n";
$foo['fname'] = 'Cliprz';
echo $foo['fname']."\n";?>
Taliesin Nuin public at taliesinnuin dot net ¶
6 years ago
You might be wondering whether implementing an ArrayAccess interface makes the class iterable. It is, after all, an "array". The answer is no, it doesn't. Additionally there are a couple of subtle gotchas if you add both and want it to be an associate array. The below is a class that has both ArrayAccess AND Iterator interfaces. And Countable as well just to be complete.
<?php
class HandyClass implements ArrayAccess, Iterator, Countable {
private
$container = array(); private $keys = array(); private $position; public function __construct() {
$position = 0;$this->container = array( "a" => 1, "b" => 2,
"c" => 3,
);
$this->keys = array_keys($this->container);
}
public function
count() : int { return count($this->keys); }
public function
rewind() { $this->position = 0; }
public function
current() { return $this->container[$this->keys[$this->position]];
}
public function
key() { return $this->keys[$this->position];
}
public function
next() { ++$this->position;
}
public function
valid() { return isset($this->keys[$this->position]);
}
public function
offsetSet($offset, $value) { if(is_null($offset)) {
$this->container[] = $value;
$this->keys[] = array_key_last($this->container); } else {
$this->container[$offset] = $value;
if(!in_array($offset, $this->keys)) $this->keys[] = $offset;
}
}
public function
offsetExists($offset) {
return isset($this->container[$offset]);
}
public function
offsetUnset($offset) {
unset($this->container[$offset]);
unset($this->keys[array_search($offset,$this->keys)]);
$this->keys = array_values($this->keys); } public function offsetGet($offset) {
return isset($this->container[$offset]) ? $this->container[$offset] : null;
}
}
?>
Example usages:
<?php
$myClass = new HandyClass();
echo('Number of elements: ' . count($myClass) . "\n\n");
echo(
"Foreach through the built in test elements:\n");
foreach($myClass as $key => $value) {
echo("$value\n");
}
echo("\n");$myClass['d'] = 4;
$myClass['e'] = 5;
echo('Number of elements after adding two: ' . count($myClass) . "\n\n");
unset(
$myClass['a']);
echo('Number of elements after removing one: ' . count($myClass) . "\n\n");
echo(
"Accessing an element directly:\n");
echo($myClass['b'] . "\n\n");$myClass['b'] = 5;
echo("Foreach after changing an element:\n");
foreach($myClass as $key => $value) {
echo("$value\n");
}
echo("\n");
?>
Hayley Watson ¶
12 years ago
The indexes used in an ArrayAccess object are not limited to strings and integers as they are for arrays: you can use any type for the index as long as you write your implementation to handle them. This fact is exploited by the SplObjectStorage class.
7 years ago
Although $offset can be anything, a string that looks like an integer is cast to integer before the call to any of the methods.
$x[1] offset is integer 1
$x['1'] offset is integer 1
$x['1.'] offset is string '1.'
msherazjaved at gmail dot com ¶
5 years ago
An experimental check addition to the findings of Per (on offsetExists method) added here (8 years ago).
<?php
class obj implements ArrayAccess {
private $container = array();
public function
__construct() {
$this->container = array(
"one" => 1,
"two" => 2,
"three" => 3,
);
}
public function
offsetSet($offset, $value) {
print "offsetSet method Triggered";
if (
is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
}
public function
offsetExists($offset) {
print "offsetExists method Triggered";
return isset(
$this->container[$offset]);
}
public function
offsetUnset($offset) {
print "offsetUnset method Triggered";
unset(
$this->container[$offset]);
}
public function
offsetGet($offset) {
print "offsetGet method Triggered";
return isset(
$this->container[$offset]) ? $this->container[$offset] : null;
}
}$obj = new obj;$obj['two'] = '2'; isset($obj['two']); unset($obj['two']); return $obj['two']; ?>
ivan dot dossev at gmail dot com ¶
12 years ago
Sadly you cannot assign by reference with the ArrayAccess (at least in PHP 5.3.23)
It's too bad there is no syntax for optionally passing variables by reference to functions (a feature in retro PHP).
That option would have let ArrayAccess fully mimic the functionality of normal array assignments:
<?php
$var = 'hello';
$arr = array();
$arr[0] = $var;
$arr[1] = &$var;
$var = 'world';
var_dump($arr[0], $arr[1]);?>
Declaring "function offsetSet($offset, &$value)" will cause a fatal error.
So to assign by ref you can use an ugly function call, for example:
<?php
class obj implements ArrayAccess {public function &offsetSetRef($offset, &$value) {
if (is_null($offset)) {
$this->container[] = &$value;
} else {
$this->container[$offset] = &$value;
}
return $value; }
}$var = 'hello';
$obj = new obj();
$obj[0] = $var;
$obj->offsetSetRef(1, $var); $var = 'world';
var_dump($obj[0], $obj[1]);?>
kaRemovTihsjouni at gmAndTihsaildot com ¶
9 years ago
reset() method may not work as you expect with ArrayAccess objects.
Using reset($myArrayAccessObject) returns the first property from $myArrayAccessObject, not the first item in the items array.
If you want to use the reset() method to return the first array item, then you can use the following simple workaround:
<?php
class MyArrayAccessObject implements Iterator, ArrayAccess, Countable {
protected $first = null; protected $items = null;
private function supportReset() {
$this->first = reset($this->items); }
public function offsetSet($offset, $value) {
if ($offset === null) {
$this->items[] = $value;
}
else {
$this->items[$offset] = $value;
}
$this->supportReset();
}
}
?>
Finally, call $this->supportReset() in the end of all methods that change the internal $items array, such as in offsetSet(), offsetUnset() etc.
This way, you can use the reset() method as normally:
<?php
$firstArrayItem = reset($myArrayAccessObject);
?>
max at flashdroid dot com ¶
15 years ago
Objects implementing ArrayAccess may return objects by references in PHP 5.3.0.
You can implement your ArrayAccess object like this:
class Reflectable implements ArrayAccess {
public function set($name, $value) {
$this->{$name} = $value;
}
public function &get($name) {
return $this->{$name};
}
public function offsetGet($offset) {
return $this->get($offset);
}
public function offsetSet($offset, $value) {
$this->set($offset, $value);
}
...
}
This base class allows you to get / set your object properties using the [] operator just like in Javascript:
class Boo extends Reflectable {
public $name;
}
$obj = new Boo();
$obj['name'] = "boo";
echo $obj['name']; // prints boo
ProgMiner ¶
7 years ago
Maybe it help anyone, if you do
<?php
$arrayAccessObject[] = 'foo';
?>
PHP give you an empty string as $offset to offsetSet($offset, $value) method.
11 years ago
Objects implementing ArrayAccess do not support the increment/decrement operators ++ and --, unlike array() and ArrayObject()
<?phpclass MyArray implements ArrayAccess
{
}$x = new MyArray() ;
$x[0] = 0 ;
$x[0]++ ; $x[0] += 1 ; ?>
jordistc at gmail dot com ¶
8 years ago
You can use the array functions on a object of a class that implements ArrayAccess using the __invoke magic method in this way:
<?php
class ArrayVar implements ArrayAccess
{
private $data = [];
public function
__invoke()
{
return $this->data;
}
}
?>
Now you can use it in this way:
<?php
$arrayar = new ArrayVar();
$arrayar['one'] = 'primer';
$arrayar['two'] = 'segon';
$arrayar['three'] = 'tercer';$keys = array_keys($arrayar());
var_dump($keys);
$diff = array_diff($arrayar(), [ 'two' => 'segon']);
var_dump($diff);
?>
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.3