Skip to content

Instantly share code, notes, and snippets.

@bxt
Created March 31, 2011 17:54
Show Gist options
  • Save bxt/896873 to your computer and use it in GitHub Desktop.
Save bxt/896873 to your computer and use it in GitHub Desktop.
Access PHP-objects' getters and setter like an array
<?php
namespace bxt\Util;
class ArrayObject implements \ArrayAccess, \Iterator, \Countable {
private $object;
private $iterator=0;
private $offsetMethodMap=array();
private $offsetMethodMapSetters=array();
public function __construct($obj) {
$this->object=$obj;
$rc=new \ReflectionClass($obj);
$meths=$rc->getMethods(\ReflectionMethod::IS_PUBLIC);
foreach($meths as $m) {
$n=$m->getShortName();
$n2=lcfirst(substr($n,3));
if(strpos($n,'get')===0 && $m->getNumberOfRequiredParameters()==0) {
$this->offsetMethodMap[$n2]=$m;
}
if(strpos($n,'set')===0 && $m->getNumberOfRequiredParameters()==1) {
$this->offsetMethodMapSetters[$n2]=$m;
}
}
}
public function offsetSet($offset,$value) {
if(isset($this->offsetMethodMapSetters[$offset]))
return $this->offsetMethodMapSetters[$offset]->invoke($this->object,$value);
throw new \OutOfRangeException("Tried to write an attribute without appropriate setter. ");
}
public function offsetExists($offset) {
return isset($this->offsetMethodMap[$offset]);
}
public function offsetUnset($offset) {
$this->offsetSet($offset,null);
}
public function offsetGet($offset) {
if(!$this->offsetExists($offset))
throw new \OutOfRangeException("Tried to read an attribute without appropriate getter. ");
return $this->offsetMethodMap[$offset]->invoke($this->object);
}
public function rewind() {
$this->iterator=0;
}
public function current() {
$i=0;
foreach($this->offsetMethodMap as $key=>$val) {
if($i==$this->iterator) return $this->offsetGet($key);
$i++;
}
return false;
}
public function key() {
$i=0;
foreach($this->offsetMethodMap as $key=>$val) {
if($i==$this->iterator) return $key;
$i++;
}
}
public function next() {
$this->iterator++;
$i=0;
foreach($this->offsetMethodMap as $key=>$val) {
if($i==$this->iterator) return $this->offsetGet($key);
$i++;
}
}
public function valid() {
return $this->current() !== false;
}
public function count() {
return count($this->offsetMethodMap);
}
}
<?php
namespace bxt\Util;
class Testclass {
function __construct($f='') {
$this->foo=$f;
}
function getFoo() {
return $this->foo;
}
function getBar() {
return "barcnt";
}
function getXXX($a) {}
function setFoo($f) {
$this->foo=$f;
}
function setXXX() {}
}
class ArrayObjectTest extends \PHPUnit_Framework_TestCase {
/**
* @dataProvider feedValues
*/
public function testSimpleGet($x) {
$t=new Testclass($x);
$o=new ArrayObject($t);
$this->assertEquals($x,$o['foo']);
$this->assertEquals('barcnt',$o['bar']);
}
/**
* @dataProvider feedValues
*/
public function testSimpleSet($x) {
$t=new Testclass("foocnt");
$o=new ArrayObject($t);
$this->assertEquals('foocnt',$o['foo']);
$o['foo']=$x;
$this->assertEquals($x,$o['foo']);
}
public function testIsset() {
$t=new Testclass("foocnt");
$o=new ArrayObject($t);
$this->assertTrue(isset($o['foo']));
$this->assertTrue(isset($o['bar']));
$this->assertFalse(isset($o['XXX']));
}
/**
* @expectedException \OutOfRangeException
*/
public function testSetFail() {
$t=new Testclass();
$o=new ArrayObject($t);
$this->assertEquals('barcnt',$o['bar']);
$o['bar']='newbarcnt';
}
/**
* @expectedException \OutOfRangeException
*/
public function testGetFail() {
$t=new Testclass();
$o=new ArrayObject($t);
$this->assertEquals('barcnt',$o['XXX']);
}
public function testCount() {
$t=new Testclass();
$o=new ArrayObject($t);
$this->assertEquals(2,count($o));
}
/**
* @dataProvider feedValues
*/
public function testForeach($x) {
$t=new Testclass($x);
$o=new ArrayObject($t);
$keys=array('foo','bar');
$vals=array($x,'barcnt');
$i=0;
foreach($o as $key=>$val) {
$this->assertEquals($keys[$i],$key);
$this->assertEquals($vals[$i],$val);
$i++;
}
}
function feedValues() {
return array(
array('string value'),
array(new \stdClass()),
array(12),
array(false),
array(true),
array(array('a','b')),
);
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment