A Namespaced registry (I was bored)
Posted: Mon Jan 08, 2007 4:30 am
When I get in to the office in the morning I usually make a cup of coffee, then another coffee and write some non-work-related code to get into the swing of things 
I wrote this today.... relatively pointless and "obvious" but here it is all the same. It's just a registry that can contain sub-registries, which in turn can contain sub-registries and so-on making a tree. It does provide a clean way to namespace your registry though.
Testcase
Example
I wrote this today.... relatively pointless and "obvious" but here it is all the same. It's just a registry that can contain sub-registries, which in turn can contain sub-registries and so-on making a tree. It does provide a clean way to namespace your registry though.
Code: Select all
<?php
/**
* A simple registry with a tree structure for namespacing
* Just the result of some procrastinating at work
* @author d11wtq - Chris Corbyn
*/
class TreeRegistry
{
/**
* A singleton instance, purely for convenience
* @static
* @var TreeRegistry
*/
protected static $instance = null;
/**
* Registered objects
* @var array
*/
protected $entries = array();
/**
* Children (branches)
* @var array TreeRegistry
*/
protected $children = array();
/**
* Create and/or fetch a singleton
* @static
* @return TreeRegistry
*/
public static function getInstance()
{
if (self::$instance === null) { self::$instance = new TreeRegistry(); }
return self::$instance;
}
/**
* Register a new child branch (namespace)
* @param string The name of the branch
*/
public function createChild($name)
{
$this->children[$name] = new TreeRegistry();
}
/**
* Unregister a child branch
* @param string The name of the branch
*/
public function removeChild($name)
{
if (isset($this->children[$name])) { unset($this->children[$name]); }
}
/**
* Magic Method to get the instance of the child
* @param string The name of the requested property
* @return TreeRegistry
*/
public function __get($property)
{
if (isset($this->children[$property]))
{
return $this->children[$property];
}
else
{
return null;
}
}
/**
* Register an object in the registry
* @param Object The object being registered
* @param string A key to identify the object by
*/
public function register($object, $key)
{
$this->entries[$key] = $object;
}
/**
* Check if an object has been registered
* @param string The key used to identify the object
*/
public function has($key)
{
return isset($this->entries[$key]);
}
/**
* Get an object back out of the registry
* @param string The key used to register the object
* @return Object
* @throws Exception If the item is not registered
*/
public function get($key)
{
if ($this->has($key))
{
return $this->entries[$key];
}
else
{
throw new Exception("No such item [" . $key . "] is registered here");
}
}
/**
* Unregister a registered object
* @param string The key used to identify the object
*/
public function unregister($key)
{
if ($this->has($key)) { unset($this->entries[$key]); }
}
}Code: Select all
<?php
require_once "/home/d11wtq/simpletest/unit_tester.php";
require_once "/home/d11wtq/simpletest/reporter.php";
require_once "/home/d11wtq/simpletest/mock_objects.php";
require_once "./TreeRegistry.php";
class Nothing {}
Mock::Generate("Nothing");
class TestOfTreeRegistry extends UnitTestCase
{
public function testRegisteredObjectsAreReturnedByReference()
{
$mock1 = new MockNothing();
$mock2 = new MockNothing();
$registry = new TreeRegistry();
$registry->register($mock1, "one");
$registry->register($mock2, "two");
$this->assertReference($mock1, $registry->get("one"));
$this->assertReference($mock2, $registry->get("two"));
}
public function testRegistryCanSeeIfObjectsAreRegistered()
{
$mock1 = new MockNothing();
$mock2 = new MockNothing();
$registry = new TreeRegistry();
$this->assertFalse($registry->has("one"));
$registry->register($mock1, "one");
$this->assertTrue($registry->has("one"));
$this->assertFalse($registry->has("two"));
$registry->register($mock2, "two");
$this->assertTrue($registry->has("two"));
}
public function testRegisteredObjectsCanBeUnregistered()
{
$mock1 = new MockNothing();
$mock2 = new MockNothing();
$registry = new TreeRegistry();
$registry->register($mock1, "one");
$this->assertTrue($registry->has("one"));
$registry->register($mock2, "two");
$this->assertTrue($registry->has("two"));
$registry->unregister("one");
$this->assertFalse($registry->has("one"));
$registry->unregister("two");
$this->assertFalse($registry->has("two"));
}
public function testExceptionIsThrownIfUnregisteredObjectIsRequested()
{
$registry = new TreeRegistry();
$mock1 = new MockNothing();
$registry->register($mock1, "one");
try {
$o = $registry->get("one");
$this->pass();
} catch (Exception $e) {
$this->fail("No exception should be thrown since 'one' is registered");
}
try {
$o = $registry->get("two");
$this->fail("An exception should have been thrown since 'two' is not registered");
} catch (Exception $e) {
$this->pass();
}
}
public function testChildrenCanBeSpawned()
{
$registry = new TreeRegistry();
$registry->createChild("foo");
$this->assertIsA($registry->foo, "TreeRegistry");
$registry->createChild("bar");
$this->assertIsA($registry->bar, "TreeRegistry");
}
public function testBranchesCanBeRemovedOnceCreated()
{
$registry = new TreeRegistry();
$this->assertFalse($registry->foo);
$registry->createChild("foo");
$this->assertTrue($registry->foo);
$registry->removeChild("foo");
$this->assertFalse($registry->foo);
}
public function testSingletonFactoryReturnsASingleton()
{
$registry1 = TreeRegistry::getInstance();
$registry2 = TreeRegistry::getInstance();
$this->assertReference($registry1, $registry2);
}
}
$test = new TestOfTreeRegistry();
$test->run(new HtmlReporter());Code: Select all
class Foo {}
class Bar {}
$registry = TreeRegistry::getInstance();
$registry->register(new Foo(), "foo");
$registry->register(new Bar(), "bar");
//Make a namespace?
$registry->createChild("ns1");
$registry->ns1->register(new Foo(), "foo");
$registry->ns2->register(new Bar(), "bar");
//and another?
$registry->ns1->createChild("ns2");
$registry->ns1->ns2->register(new Foo(), "foo");
var_dump($registry->ns1->get("foo"));