OO 'Deep' registry..
Posted: Sun Mar 18, 2007 2:17 am
Ambiguous title, I apolgise. I couldn't think up anything more descriptive. I've not unit tested it, I've not I've got the effort to just yet. Will do at a later date. 
EDIT: Added comments
Usage example:
Small blog for it..
Inspired by Java's "Properties" file format, and of course the Windows registry. I didn't really 'need' this for anything, other than a challenge* and time filling (insomnia strikes,) though I forsee I will use it in the future as I like to organise my data, objects, and anything else I see fit for use in a registry. I am not 100% satisfied with the masses of loops.. I would prefer to have the string looped in one method only, but because even though the loops all do the same (i.e. move along the sections of the string) the inner bits of the loops do otherwise.. I might even make an iterator object for the string in future, but that's 'overkill' atm.
If anyone is nuts like me and wants to use this, please do - but please do include a link to where you found it.. "Jenk on http://www.devnetwork.net" is all that is required.
*I plan on O/RM'ing this.. wish me luck
EDIT: Added comments
Code: Select all
<?php
/**
* Registry Manager
*
* This class is the controller for the registry
* @author Jenk
*/
class RegistryManager
{
/**
* The root object of the registry.
* @var RegistryKey
*/
private $_keys;
/**
* The token for which to identify where the names of the string split
* e.g. registry/key/anotherkey would be registry -> key -> anotherkey
* @const string
*/
const SPLITTER = '/';
/**
* _split function; what converts the string to an array of keys.
* @param string $key
* @returns array
*/
private function _split ($key)
{
$key = trim ($key, self::SPLITTER);
return explode(self::SPLITTER, $key);
}
/**
* Lazy loader for the root registry object
* @returns RegistryKey
*/
private function _getKeys()
{
if (!($this->_keys instanceof RegistryKey)) $this->_keys = new RegistryKey;
return $this->_keys;
}
/**
* Add key to the registry, and assign a value.
* Assigns value blindly - i.e. previous values will be overwritten without warning.
* @param string $name
* @param mixed $value
*/
public function addKey ($name, $value)
{
$parts = $this->_split($name);
$pos = $this->_getKeys();
foreach ($parts as $part)
{
if (!$pos->keyExists($part))
{
$stub = new RegistryKey();
$pos->addKey($part, $stub);
$pos =& $stub;
unset($stub); // necessary for dereferencing.
}
else
{
$pos = $pos->getKey($part);
}
}
$pos->value = $value;
}
/**
* Check if $key exists
* @param string $key
* @returns bool
*/
public function keyExists ($key)
{
$parts = $this->_split($key);
$pos = $this->_getKeys();
foreach ($parts as $part)
{
if (!$pos->keyExists($part))
{
return false;
}
else
{
$pos = $pos->getKey($part);
}
}
return true;
}
/**
* Retrieve RegistryKey $key
* @throws Exception
* @param string $key
*/
public function getKey ($key)
{
if (!$this->keyExists($key)) throw new Exception('Key does not exist.');
$parts = $this->_split($key);
$pos = $this->_getKeys();
foreach ($parts as $part)
{
$pos = $pos->getKey($part);
}
return $pos;
}
/**
* Convenience function, retrieves the value of $key, and not the key itself.
* @returns mixed
*/
public function getValue ($key)
{
return $this->getKey($key)->value;
}
}
/**
* RegistryKey class, the registry key object which contains the value.
*
* @author Jenk
*/
class RegistryKey
{
/**
* The container for child RegistryKey objects
* @var array
*/
private $_keys = array();
/**
* The container for the value of this key
* @var mixed
*/
public $value = null;
/**
* Add a child key
* @throws Exception
* @param string $name
* @param RegistryKey $key
*/
public function addKey ($name, RegistryKey $key)
{
$this->_keys[$name] = $key;
}
/**
* Check if child key exists
* Note: this does not search the full tree, it will only check if $name is
* an existing child key. If $key = "some/registry/branch" it will look for
* a child called exactly that and not a branch.
* @param string $name
* @returns bool
*/
public function keyExists ($name)
{
return isset($this->_keys[$name]);
}
/**
* Returns the RegistryKey object of $name.
* Note: This does not search the full tree. If $key = "some/registry/branch"
* it will look for a child called exactly that, not the branch.
* @throws Exception
* @param string $key
* @returns RegistryKey
*/
public function getKey ($key)
{
if (!$this->keyExists($key)) throw new Exception('Key does not exist.');
else return $this->_keys[$key];
}
/**
* Convenience function for returning the value of the RegistryKey $key,
* instead of the object.
* @returns mixed
*/
public function getValue($key)
{
return $this->getKey($key)->value;
}
/**
* Convenience function for adding new values
* Does not search tree, but adds values with name as literal.
* WARNING: Adding keys which contain the RegistryManager::SPLITTER will break search functionality!
*
* @param string $name
* @param mixed $value
*/
public function addValue ($name, $value)
{
if (!$this->keyExists($name))
{
$newKey = new RegistryKey;
$newKey->value = $value;
$this->addKey($name, $newKey);
}
else
{
$newKey = $this->getKey($name);
$newKey->value = $value;
}
}
}
$reg = new RegistryManager;
$keyString = 'a/b/c';
$reg->addKey($keyString, 'value');
echo $reg->getValue($keyString); // 'value'
var_dump($reg->keyExists('a/b')); // 'bool(true)'
var_dump($reg->keyExists('a/b/d')); // 'bool(false)'
?>Code: Select all
$reg = new RegistryManager;
$reg->addKey('Database/Password', 'pass');
$reg->addKey('Database/Username', 'user');
$reg->addKey('Database/Address', 'addy');
// later on..
$dbinfo = $reg->getKey('Database');
mysql_connect($dbinfo->getValue('Username'), $dbinfo->getValue('Password'), $dbinfo->getValue('Address'));Inspired by Java's "Properties" file format, and of course the Windows registry. I didn't really 'need' this for anything, other than a challenge* and time filling (insomnia strikes,) though I forsee I will use it in the future as I like to organise my data, objects, and anything else I see fit for use in a registry. I am not 100% satisfied with the masses of loops.. I would prefer to have the string looped in one method only, but because even though the loops all do the same (i.e. move along the sections of the string) the inner bits of the loops do otherwise.. I might even make an iterator object for the string in future, but that's 'overkill' atm.
If anyone is nuts like me and wants to use this, please do - but please do include a link to where you found it.. "Jenk on http://www.devnetwork.net" is all that is required.
*I plan on O/RM'ing this.. wish me luck