Lazy Registry Class
Een Registry klasse is een klasse waarin je objecten kunt opslaan, zodat je ze ergens anders weer kunt gebruiken. Een voorbeeld hiervan is je PDO instantie. Die is nodig bij een hoop klassen, en je wilt deze misschien niet de hele tijd doorgeven in de constructors. Je kunt dan het object via de method Registry::set($name, $object) registreren, en later weer ophalen via Registry::get($name). Je benadert de Registry class via static methods zodat je niet steeds een referentie van de juiste instantie hoeft door te geven. Binnenin de Registry wordt via een singleton één echte instantie van Registry aangemaakt. Met deze klasse kun je objecten ook lazy registreren. Lazy registreren houdt in dat het object dat je registreert pas echt wordt aangemaakt als je het voor het eerst gebruikt. Dit kan handig zijn als je niet zeker weet of hij gebruikt gaat worden. Je kunt in deze Registry klasse een object lazy laten registreren door alleen de naam van de klasse en eventuele argumenten op te geven, maar ook door er nog een naam van een statische methode aan toe te voegen. Ik hoop dat het nut van de klasse zo duidelijk is. En ik hoop dat het gebruik samen met de documentatie in de klasse ook duidelijk is. Ik weet dat er al een hoop Registry klassen bestaan op het internet, maar ik heb er weinig gezien waarbij je classes lazy kunt registreren. Vandaar dat ik deze klasse post. Het is namelijk niet gemakkelijk om dit te implementeren. Na lang zoeken heb ik gebruik gemaakt van de Reflection API van PHP, en dat blijkt erg goed te werken. Uiteraard is dit alleen een begin en kun je dit nog een heel eind uitbreiden en/of aan je eigen stijl aanpassen. De basis, en daarmee het lastigste is echter alvast gelegd. Changelog: - Clone en unserialisatie preventie weggehaald omdat het onmogelijk is om aan in instantie van Registry te komen, en het dus ook niet mogelijk is om hem te clonen of te serialiseren. - Er voor gezorgd dat je niet een lazy object en een normaal object onder dezelfde naam kunt registreren.
Gebruiksvoorbeeld (niet getest):
<?php
//Lazy load
$args = array('pgsql:host=localhost port=5432 dbname=testdb',
'testuser',
'testpass',
array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
Registry::setLazy('dbconn1', 'PDO', $args);
//Ophalen van object
$db = Registry::get('dbconn1');
//Lazy load met static method voor bijvoorbeeld singleton
$args = array('localhost',
5432,
'testuser',
'testpass',
'testdb');
Registry::setLazy('dbconn2', 'dbClass', $args, 'singleton');//Bij initialisatie van dbClass wordt de static method 'singleton' dus aangeroepen (en er wordt een return-value verwacht)
//Ophalen gaat weer hetzelfde
$db = Registry::get('dbconn2');
//Zonder lazy load
$db = new PDO('pgsql:host=localhost port=5432 dbname=testdb',
'testuser',
'testpass',
array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
Registry::set('dbconn3', $db);
//En ophalen gaat weer hetzelfde
$db2 = Registry::get('dbconn3');
?>
De Registry class
<?php
/**
* Lazy Registry class
*
* A class you can use to register objects, so you can always find the object.
* It is possible to register a object lazy, so it is created when needed.
*
*/
class Registry {
/**
* Internal variable holding a instance of Registry for the singleton created by Registry::getInstance().
*
* @var Registry
*/
private static $instance;
/**
* Internal variable holding a array of registered objects.
*
* @var array
*/
protected $objects = array();
/**
* The constructor is only created to prevent the Registry class from direct creation of objects.
* This is done by giving it private and final modifiers.
*
*/
private final function __construct() {
}
/**
* Internal method that creates an instance of Registry when it does not exist. Then it returns the instance.
*
* @return Registry
*/
private static function getInstance() {
if (!isset(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
/**
* With this method you can register a new object in the Registry.
*
* @param string $name
* @param object $object
*/
public static function set($name, $object) {
if (!is_string($name)) {
throw new RegistryException('Parameter $name is not a string.', RegistryException::INVALID_PARAMETER);
}
if (!is_object($object)) {
throw new RegistryException('Parameter $object is not a object.', RegistryException::INVALID_PARAMETER);
}
$instance = self::getInstance();
$instance->objects[$name] = $object;
}
/**
* With this method you can register a object lazy in the registry.
* This means that it will be created wen it is needed.
*
* @param string $name
* @param string $className
* @param array $args
* @param string $staticMethod
*/
public static function setLazy($name, $className, array $args = array(), $staticMethod = null) {
if (!is_string($name)) {
throw new RegistryException('Parameter $name is not a string.', RegistryException::INVALID_PARAMETER);
}
if (!class_exists($className)) {
throw new RegistryException('Parameter $className does not contain a defined classname.', RegistryException::INVALID_PARAMETER);
}
if (!is_null($staticMethod)) {
if (!is_string($staticMethod)) {
throw new RegistryException('Parameter $staticMethod is not a static method name.', RegistryException::INVALID_PARAMETER);
}
$reflectionClass = new ReflectionClass($className);
if (!$reflectionClass->hasMethod($staticMethod)) {
throw new RegistryException('Parameter $staticMethod is not a static method name.', RegistryException::INVALID_PARAMETER);
}
$reflectionMethod = $reflectionClass->getMethod($staticMethod);
if (!$reflectionMethod->isStatic() || !$reflectionMethod->isPublic()) {
throw new RegistryException('Parameter $staticMethod is not a static method name.', RegistryException::INVALID_PARAMETER);
}
}
$instance = self::getInstance();
$instance->objects[$name] = array($className, $args, $staticMethod);
}
/**
* With this method you can get a registered object. Objects who are registered lazy will be created.
*
* @param string $name
* @return object
*/
public static function get($name) {
if (!is_string($name)) {
throw new RegistryException('Parameter $name is not a string.', RegistryException::INVALID_PARAMETER);
}
$instance = self::getInstance();
if (array_key_exists($name, $instance->objects)) {
if (is_array($instance->objects[$name])) {
$reflectionClass = new ReflectionClass($instance->objects[$name][0]);
if (is_null($instance->objects[$name][2])) {
$instance->objects[$name] = $reflectionClass->newInstanceArgs($instance->objects[$name][1]);
} else {
$instance->objects[$name] = $reflectionClass->getMethod($instance->objects[$name][2])->invokeArgs(null, $instance->objects[$name][1]);
}
return $instance->objects[$name];
}
return $instance->objects[$name];
}
return false;
}
}
/**
* Exception class for the Registry class
*
*/
class RegistryException extends Exception {
/**
* When this constant is given as code in a throw, there is an unknown error.
*
*/
const UNKNOWN = 0;
/**
* When this constant is given as code in a throw, there is given a wrong parameter to a method of Registry.
*
*/
const INVALID_PARAMETER = 2;
}
?>
Reacties
0