I implement ArrayAccess
in some of my classes and often, I use almost exactly the same code for the ArrayAccess methods in my class as are in Example #1 on the ArrayAccess docs.
Since the code is the same, it would be nice to write this once as a Trait, and then my classes can just implement ArrayAccess
(as now), and use ArrayAccessTrait
without needing to duplicate a bunch of ArrayAccess methods.
The only thing preventing this is that I usually don't want my underlying array named $container
, but something else more pertinent to the class I'm building.
So my question is, is there a way to "alias" whatever array property name I'm using within my own class with the $container
being used in my ArrayAccessTrait
?
The example below has a Foo
class that shows what I want; this example works, but I'd like to be able to use a property named something other than $container
within the Foo
class.
trait ArrayAccessTrait {
private $container = [];
public function offsetSet($offset, $value) {
if (is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
}
public function offsetExists($offset) {
return isset($this->container[$offset]);
}
public function offsetUnset($offset) {
unset($this->container[$offset]);
}
public function offsetGet($offset) {
return isset($this->container[$offset]) ? $this->container[$offset] : null;
}
}
class Foo implements ArrayAccess {
use ArrayAccessTrait;
private $container = [];
public function __construct() {
$this->container = [
"one" => 1,
"two" => 2,
"three" => 3,
];
}
public function hello($msg = 'Hello World') {
echo $msg . "<br/>\n";
}
}
$obj = new Foo;
$obj->hello();
echo "Array accessing element ['two'] = " . $obj['two'];
If you're defining private attributes in a trait, you arguably shouldn't be referring to them directly in the classes that implement it. Instead, just use the methods in the trait. I.e., instead of doing this in the concrete class:
$this->container["one"] = 1;
Do this:
$this["one"] = 1;
Then you don't need to know what the storage attribute is called, and you don't need to write any code around setting/getting it. Note also that you do not need to redefine private $container = [];
in your class, as it already comes with the trait.