From 46e8d3cbe6ece264f9f2e252a3c39c7929796ed0 Mon Sep 17 00:00:00 2001 From: Dominik Liebler Date: Fri, 23 Sep 2016 10:47:24 +0200 Subject: [PATCH] PHP7 Registry --- Structural/Registry/README.rst | 3 +- Structural/Registry/Registry.php | 37 ++++++++++++---------- Structural/Registry/Tests/RegistryTest.php | 31 +++++++++++++++--- 3 files changed, 49 insertions(+), 22 deletions(-) diff --git a/Structural/Registry/README.rst b/Structural/Registry/README.rst index 8a92604..1702c9b 100644 --- a/Structural/Registry/README.rst +++ b/Structural/Registry/README.rst @@ -6,7 +6,8 @@ Purpose To implement a central storage for objects often used throughout the application, is typically implemented using an abstract class with only -static methods (or using the Singleton pattern) +static methods (or using the Singleton pattern). Remember that this introduces +global state, which should be avoided at all times! Instead implement it using Dependency Injection! Examples -------- diff --git a/Structural/Registry/Registry.php b/Structural/Registry/Registry.php index e40d0c3..dccaf6f 100644 --- a/Structural/Registry/Registry.php +++ b/Structural/Registry/Registry.php @@ -2,46 +2,51 @@ namespace DesignPatterns\Structural\Registry; -/** - * class Registry. - */ abstract class Registry { const LOGGER = 'logger'; /** + * this introduces global state in your application which can not be mocked up for testing + * and is therefor considered an anti-pattern! Use dependency injection instead! + * * @var array */ - protected static $storedValues = array(); + private static $storedValues = []; + + /** + * @var array + */ + private static $allowedKeys = [ + self::LOGGER, + ]; /** - * sets a value. - * * @param string $key * @param mixed $value * - * @static - * * @return void */ - public static function set($key, $value) + public static function set(string $key, $value) { + if (!in_array($key, self::$allowedKeys)) { + throw new \InvalidArgumentException('Invalid key given'); + } + self::$storedValues[$key] = $value; } /** - * gets a value from the registry. - * * @param string $key * - * @static - * * @return mixed */ - public static function get($key) + public static function get(string $key) { + if (!in_array($key, self::$allowedKeys) || !isset(self::$storedValues[$key])) { + throw new \InvalidArgumentException('Invalid key given'); + } + return self::$storedValues[$key]; } - - // typically there would be methods to check if a key has already been registered and so on ... } diff --git a/Structural/Registry/Tests/RegistryTest.php b/Structural/Registry/Tests/RegistryTest.php index 9561abe..63053db 100644 --- a/Structural/Registry/Tests/RegistryTest.php +++ b/Structural/Registry/Tests/RegistryTest.php @@ -9,12 +9,33 @@ class RegistryTest extends \PHPUnit_Framework_TestCase public function testSetAndGetLogger() { $key = Registry::LOGGER; - $object = new \StdClass(); + $logger = new \stdClass(); - Registry::set($key, $object); - $actual = Registry::get($key); + Registry::set($key, $logger); + $storedLogger = Registry::get($key); - $this->assertEquals($object, $actual); - $this->assertInstanceOf('StdClass', $actual); + $this->assertSame($logger, $storedLogger); + $this->assertInstanceOf('stdClass', $storedLogger); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testThrowsExceptionWhenTryingToSetInvalidKey() + { + Registry::set('foobar', new \stdClass()); + } + + /** + * notice @runInSeparateProcess here: without it, a previous test might have set it already and + * testing would not be possible. That's why you should implement Dependency Injection where an + * injected class may easily be replaced by a mockup + * + * @runInSeparateProcess + * @expectedException \InvalidArgumentException + */ + public function testThrowsExceptionWhenTryingToGetNotSetKey() + { + Registry::get(Registry::LOGGER); } }