Singleton Class saves resources
There are several ways to implement singleton classes.
In all methods, the class instance is created as
\Namespace\ClassName::getInstance()
Method 1:
protected static $instances = array();// to solve the issue https://stackoverflow.com/questions/17632848/php-sub-class-static-inheritance-children-share-static-variables
/**
* @brief Singleton Constructor
*
* @return ClassInstance
*
* @details Caution: never call Class::getInstance() in another class's constructor, that instance will be discarded from $instances array
*/
public static function getInstance()// Caution: never call Class::getInstance() in another class's constructor
{
//https://www.php.net/manual/en/reflectionclass.newinstancewithoutconstructor.php &
//https://refactoring.guru/design-patterns/singleton/php/example
$ref = new \ReflectionClass( get_called_class() ) ;
$reflectionProperty = new \ReflectionProperty(static::class, 'instances');
$reflectionProperty->setAccessible(true);
//echo $reflectionProperty->getValue();
$instances = $reflectionProperty->getValue();;//$reflectedClass->getStaticPropertyValue('inst');
$intentedClass = static::class;
if ( !isset($instances[$intentedClass]))
{
// The magic.
//$ctor->setAccessible( true ) ;
//$inst = new static();
$instances[$intentedClass] = new static();
//echo "INSTANTIATED ".print_r($inst,true) ."<br />";
$reflectionProperty->setValue(null/* null for static var */, $instances);
//echo "<pre>". print_r(array_keys($instances),true)."</pre>";
}
return $instances[$intentedClass] ;
}//public static function getInstance()
Method 2: With 'Constructor Overloading'
protected static $instances = array();// to solve the issue https://stackoverflow.com/questions/17632848/php-sub-class-static-inheritance-children-share-static-variables
public static function getInstance()
{
//https://www.php.net/manual/en/reflectionclass.newinstancewithoutconstructor.php &
//https://refactoring.guru/design-patterns/singleton/php/example
$ref = new \ReflectionClass( get_called_class() ) ;
$reflectionProperty = new \ReflectionProperty(static::class, 'instances');
$reflectionProperty->setAccessible(true);
//echo $reflectionProperty->getValue();
$instances = $reflectionProperty->getValue();;//$reflectedClass->getStaticPropertyValue('inst');
$intentedClass = static::class;
//if ( $instances[static::class] == null)
if ( !isset($instances[$intentedClass]))
{
$arguments = func_get_args();
$numberOfArguments = func_num_args();
//die("numberOfArguments is " . $numberOfArguments );
// The magic.
//$ctor->setAccessible( true ) ;
//$inst = new static();
$instances[$intentedClass] = $numberOfArguments==0?new static():new static($arguments[0] /* $dbDetails */);
//echo "INSTANTIATED ".print_r($inst,true) ."<br />";
$reflectionProperty->setValue(null/* null for static var */, $instances);
//echo "<pre>". print_r(array_keys($instances),true)."</pre>";
}
return $instances[$intentedClass] ;
}//public static function getInstance($dbDetails)
private function __construct()
{
$arguments = func_get_args();
$numberOfArguments = func_num_args();
//die("numberOfArguments is " . $numberOfArguments );
//die("calling __construct in \MYSQL");
if (method_exists($this, $function = '__construct'.$numberOfArguments)) {
call_user_func_array(array($this, $function), $arguments);
}
}
/**
* @brief Constructor without argument
*
* @return void
*
* @details This construstor is used when this class is used as a library, where $dbDetails can be obtained from a config class of that system
*/
//--------------------------------------------------------
private function __construct0()//MySQL(
//--------------------------------------------------------
{
$siteConfig = \OsolMVC\Core\Config\ClassSiteConfig::getInstance();
$dbDetails = $siteConfig->getDBSettings();
//die("dbDetails is <pre>".print_r($dbDetails,true)."</pre>");
//die("calling __construct0 in \MYSQL");
$this->dbDetails = $dbDetails;
$this->user = $dbDetails['DB_USER'];
$this->pass = $dbDetails['DB_PASS'];
$this->server = $dbDetails['DB_SERVER'];
$this->db = $dbDetails['DB_NAME'];
$this->table_prefix = $dbDetails['table_prefix'];
$this->log_queries = $dbDetails['log_queries'];
$this->query_log_type = $dbDetails['query_log_type'];
$this->connectdb();
}//private function __construct()
//--------------------------------------------------------
private function __construct1($dbDetails)//MySQL(
//--------------------------------------------------------
{
//die("calling __construct1 in \MYSQL");
$this->user = $dbDetails['DB_USER'];
$this->pass = $dbDetails['DB_PASS'];
$this->server = $dbDetails['DB_SERVER'];
$this->db = $dbDetails['DB_NAME'];
$this->table_prefix = $dbDetails['table_prefix'];
$this->log_queries = $dbDetails['log_queries'];
$this->query_log_type = $dbDetails['query_log_type'];
$this->connectdb();
}
Method 3. Implement it in Parent Class
Note:
- Child class constructors should be
protected
and NOTprivate
ieprotected function __construct()
-
While using this approach, Dont instantiate a singleton class inside constructor of another singleton class. when called inside constructor of another singleton class, the instance, instantiated inside constructor, is discarded after the former is instantiated.
Full Code of parent class
class CoreParent
{
protected static $instances = array();// to solve the issue https://stackoverflow.com/questions/17632848/php-sub-class-static-inheritance-children-share-static-variables
/**
* @brief Singleton Constructor
*
* @return ClassInstance
*
* @details Caution: never call Class::getInstance() in another class's constructor, that instance will be discarded from $instances array
*/
public static function getInstance()// Caution: never call Class::getInstance() in another class's constructor
{
//https://www.php.net/manual/en/reflectionclass.newinstancewithoutconstructor.php &
//https://refactoring.guru/design-patterns/singleton/php/example
$ref = new \ReflectionClass( get_called_class() ) ;
$reflectionProperty = new \ReflectionProperty(static::class, 'instances');
$reflectionProperty->setAccessible(true);
//echo $reflectionProperty->getValue();
$instances = $reflectionProperty->getValue();;//$reflectedClass->getStaticPropertyValue('inst');
$intentedClass = static::class;
//if ( $instances[static::class] == null)
if ( !isset($instances[$intentedClass]))
{
// The magic.
//$ctor->setAccessible( true ) ;
//$inst = new static();
$instances[$intentedClass] = new static();
//echo "INSTANTIATED ".print_r($inst,true) ."<br />";
$reflectionProperty->setValue(null/* null for static var */, $instances);
//echo "<pre>". print_r(array_keys($instances),true)."</pre>";
}
return $instances[$intentedClass] ;
}//public static function getInstance()
}//class CoreParent
|
|