Php5 Singleton pattern with magic __get and __set
Posted by Lon Hosford on March 30th, 2008 at 11:41am
I wanted to reproduce a simple singleton design pattern in PHP 5. After reviewing many overly complex examples, I synthesized to this example.
It also makes use of the PHP5 magic function __get and __set also poorly addressed in web postings. Going for cleaner code I like to see $obj->prop rather than $obj->getProp() and $obj->setProp(value) in the code. But I am greedy and want to have read only and write only props. So I configured the various examples to achieve that goal. As well you can see in the __set and __get methods you may choose to work the props or call a private method that would handle the validation and proper handling of the set and return values. I demonstrated this here.
This is the singleton running with the idea of a single configuration object for an application. It only has one real property named isDebugging for the example.
- <?php
- class Config {
- static private $_instance;
- private $isDebugging = false; // Read write
- private $version = "1.1" ; // Read only
- private $cannotReadProp = "x" ;
- public static function getInstance($args = array())
- {
- if(!self::$_instance)
- {
- self::$_instance = new Config();
- }
- self::$_instance->setIsDebugging(isset($args['isDebugging']) ? $args['isDebugging'] : self::$_instance->isDebugging);
- return self::$_instance;
- }
- private static function setIsDebugging($value)
- {
- self::$_instance->isDebugging = is_bool($value)? $value: self::$_instance->isDebugging;
- }
- public static function __set($prop, $value)
- {
- if (isset(self::$_instance->$prop))
- {
- switch ($prop)
- {
- case 'isDebugging':
- self::$_instance->setIsDebugging($value);
- break;
- default :
- throw new Exception('Cannot write property [' . $prop . ']',1);
- }
- }
- else
- {
- throw new Exception('Undefined property [' . $prop . ']',1);
- }
- }
- public static function __get($prop)
- {
- if (isset(self::$_instance->$prop))
- {
- switch ($prop)
- {
- case 'isDebugging':
- return self::$_instance->isDebugging;
- break;
- default :
- throw new Exception('Cannot read property [' . $prop . ']',1);
- }
- }
- else
- {
- throw new Exception('Undefined property [' . $prop . ']',1);
- }
- }
- }
- ?>
This is a testing script for the above. Note there are some commented lines for testing the exception thowing.
- <?php
- include 'config.inc.php';
- // First reference
- $myConfig1 = Config::getInstance();
- // Get property
- echo ('$myConfig1->isDebugging:' . ($myConfig1->isDebugging ? "true" : "false")) . '<br/>';
- // Set property
- echo 'Set $myConfig1->isDebugging = true <br/>';
- $myConfig1->isDebugging = true;
- echo ('$myConfig1->isDebugging:' . ($myConfig1->isDebugging ? "true" : "false")) . '<br/>';
- // Second reference
- echo '<br/>';
- echo 'Add second reference and not getInstance args<br/>';
- echo '$myConfig2 = Config::getInstance(); <br/>';
- $myConfig2 = Config::getInstance();
- echo ('$myConfig1->isDebugging:' . ($myConfig1->isDebugging ? "true" : "false")) . '<br/>';
- echo ('$myConfig2->isDebugging:' . ($myConfig2->isDebugging ? "true" : "false")) . '<br/>';
- // Third reference
- echo '<br/>';
- echo 'Add third reference and change prop via getInstance arg <br/>';
- echo '$myConfig3 = Config::getInstance(array(\'isDebugging\'=>false)); <br/>';
- $myConfig3 = Config::getInstance(array('isDebugging'=>false));
- echo ('$myConfig1->isDebugging:' . ($myConfig1->isDebugging ? "true" : "false")) . '<br/>';
- echo ('$myConfig2->isDebugging:' . ($myConfig2->isDebugging ? "true" : "false")) . '<br/>';
- echo ('$myConfig3->isDebugging:' . ($myConfig3->isDebugging ? "true" : "false")) . '<br/>';
- // Set property via second instance
- echo '<br/>';
- echo 'Set property via second instance <br/>';
- echo 'Set $myConfig2->isDebugging = true <br/>';
- $myConfig2->isDebugging = true;
- echo ('$myConfig1->isDebugging:' . ($myConfig1->isDebugging ? "true" : "false")) . '<br/>';
- echo ('$myConfig2->isDebugging:' . ($myConfig2->isDebugging ? "true" : "false")) . '<br/>';
- echo ('$myConfig3->isDebugging:' . ($myConfig3->isDebugging ? "true" : "false")) . '<br/>';
- // Set property to incorrect data type
- echo '<br/>';
- echo 'Set $myConfig1->isDebugging = 123<br/>';
- echo 'No exception for invalid data type and not prop change.<br/>';
- $myConfig1->isDebugging = 123;
- echo ('$myConfig1->isDebugging:' . ($myConfig1->isDebugging ? "true" : "false")) . '<br/>';
- echo ('$myConfig2->isDebugging:' . ($myConfig2->isDebugging ? "true" : "false")) . '<br/>';
- echo ('$myConfig3->isDebugging:' . ($myConfig3->isDebugging ? "true" : "false")) . '<br/>';
- // Setter throws undefined property exception
- //$myConfig1->test = true;
- // Getter throws undefined property exception
- //echo '$myConfig1->test:' . $myConfig1->test . '<br/>';
- // Setter throws cannot write property exception
- //$myConfig1->version = '2.2';
- // Setter throws cannot read property exception
- //echo '$myConfig1->cannotReadProp:' . $myConfig1->cannotReadProp . '<br/>';
- ?>
Under General stuff+ Php+ Php 5
Leave a Comment for Php5 Singleton pattern with magic __get and __set
You must be logged in to post a comment.
Trackback this post | Subscribe to the comments via RSS Feed