Skip to content

Instantly share code, notes, and snippets.

@firegate666
Created February 8, 2012 14:12
Show Gist options
  • Save firegate666/1769855 to your computer and use it in GitHub Desktop.
Save firegate666/1769855 to your computer and use it in GitHub Desktop.
magic property getter example with internal xml storage
<?php
/**
* Example class that holds an xml and adds magic getter and property accessors for xml nodes
* The class property annotations define type casts
*
* @property integer username
* @property string password
* @property array collection
* @property array car
*
* @author behnke
*
*/
class Proptest
{
protected $false = false;
public function getFalse()
{
return $this->false;
}
/**
*
* @var SimpleXMLElement
*/
protected $xml = null;
protected static $propMapping = null;
public function __construct()
{
$this->xml = simplexml_load_string('<?xml version="1.0"?><user><username protected="true">123456</username><password>jhdfH</password><car><drivers><driver>Stan</driver><driver>Mike</driver></drivers><type>Ford Focus</type><wheels>4</wheels></car><collection><name>tes2t</name><name>test</name><value>foobar</value></collection></user>');
}
/**
* get property type
*
* @param String $name
* @return String
*/
protected static function __get_xmlPropertyType($name)
{
if (is_null(static::$propMapping))
{
static::$propMapping = array();
$refclass = new ReflectionClass(get_called_class());
$props = $refclass->getDocComment();
preg_match_all('/@property (\w+) (\w+)/', $props, $matches, PREG_SET_ORDER);
foreach($matches as $match)
{
static::$propMapping[$match[2]] = $match[1];
}
}
if (isset(static::$propMapping[$name]))
{
return static::$propMapping[$name];
}
else
{
return null;
}
}
/**
* magic getter for xml properties
*
* @param String $function
* @param array $args
*/
public function __call($function, $args)
{
if (substr($function, 0, 3) == 'get')
{
$property = lcfirst(substr($function, 3));
return $this->__get_xmlProperty($property, true); // delegate
}
}
/**
* tests if xml property exists
*
* @param String $name
* @retun boolean
*/
protected function __has_xmlProperty($name)
{
return isset($this->xml->$name);
}
/**
* magic xml property access with typecast
*
* @param String $name
* @param boolean $protectedAllowed override protected
* @throws Exception if property is protected
* @return mixed
*/
protected function __get_xmlProperty($name, $protectedAllowed = false)
{
$type = static::__get_xmlPropertyType($name);
$value = $this->xml->$name;
if (!$protectedAllowed && isset($value['protected']) && $value['protected'] == 'true')
{
throw new Exception(sprintf('Undefined or protected property %s of class %s', $name, get_called_class()));
}
settype($value, $type);
return $value;
}
/**
* magic xml property access
*
* @uses Proptest::__get_xmlProperty(String, boolean)
* @param String $name
* @throws Exception if property is protected or does not exist
* @return mixed
*/
public function __get($name)
{
if ($this->__has_xmlProperty($name))
{
return $this->__get_xmlProperty($name);
}
else
{
throw new Exception(sprintf('Undefined or protected property %s of class %s', $name, get_called_class()));
}
}
}
function printOut($name, $value)
{
printf("%s: %s\n", $name, var_export($value, true));
}
$test = new Proptest();
printOut('getCar', $test->getCar());
printOut('collection', $test->collection);
try {
printOut('username', $test->username); // this one fails, xml protected property
} catch(Exception $e) { printOut('exception', $e->getMessage());}
printOut('getUsername', $test->getUsername());
printOut('password', $test->password);
printOut('getFalse', $test->getFalse());
try {
printOut('false', $test->false); // this one fails, object protected property
} catch(Exception $e) {
printOut('exception', $e->getMessage());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment