<?php
trait Singleton
{
private $storage; // A Temporary variable for 'quick data'
protected $methods = array(); // Anonymous Function Declaration
protected static $getInstance; // Instance of the Container
public static function __callStatic($methodName, $arguments = array())
{
return self::getInstance()->Skeleton( $methodName, $arguments );
}
public static function newInstance()
{ // Start a new instance of the class and pass any arguments
$class = new \ReflectionClass( get_called_class() );
self::$getInstance = $class->newInstanceArgs( func_get_args() );
return self::$getInstance;
}
public static function getInstance()
{ // see if the class has already been called this run
if (!empty(self::$getInstance))
return self::$getInstance;
$calledClass = get_called_class();
// check if the object has been sterilized in the session
// This will invoke the __wake up operator
if (array_key_exists( $calledClass, $_SESSION ) &&
is_object( self::$getInstance = unserialize( $_SESSION[$calledClass] )))
return self::$getInstance;
// Start a new instance of the class and pass any arguments
$class = new \ReflectionClass( get_called_class() );
self::$getInstance = $class->newInstanceArgs( func_get_args() );
return self::$getInstance;
}
/**
* @param null $object
* @return object|null
*/
public static function clearInstance($object = null)
{
self::$getInstance = is_object( $object ) ? $object : null;
if (array_key_exists( __CLASS__, $_SESSION )) unset($_SESSION[__CLASS__]);
return self::$getInstance;
}
public function __call($methodName, $arguments = array())
{
return $this->Skeleton( $methodName, $arguments );
}
private function Skeleton($methodName, $arguments = array())
{
// Have we used addMethod() to override an existing method
if (key_exists( $methodName, $this->methods ))
return (null === ($result = call_user_func_array( $this->methods[$methodName], $arguments )) ? $this : $result);
// Is the method in the current scope ( public, protected, private ).
// Note declaring the method as private is the only way to ensure single instancing
if (method_exists( $this, $methodName )) {
return (null === ($result = call_user_func_array( array($this, $methodName), $arguments )) ? $this : $result);
}
if (key_exists( 'closures', $GLOBALS ) && key_exists( $methodName, $GLOBALS['closures'] )) {
$function = $GLOBALS['closures'][$methodName];
$this->addMethod( $methodName, $function );
return (null === ($result = call_user_func_array( $this->methods[$methodName], $arguments )) ? $this : $result);
} throw new \Exception( "There is valid method or closure with the given name '$methodName' to call" );
}
private function addMethod($name, $closure)
{
if (is_callable( $closure )):
$this->methods[$name] = \Closure::bind( $closure, $this, get_called_class() );
else: // Nested to ensure Singleton returns the correct value of self
throw new \Exception( "New Method Must Be A Valid Closure" );
endif;
}
public function __wakeup()
{
if (method_exists( $this, '__construct' )) self::__construct();
$object = get_object_vars( $this );
foreach ($object as $item => $value) // TODO - were really going to try and objectify everything?
if(is_object( $temp = @unserialize($this->$item)))
$this->$item = $temp;
}
// for auto class serialization add: const Singleton = true; to calling class
public function __sleep()
{
if (!defined( 'self::Singleton' ) || !self::Singleton) return null;
$object = get_object_vars( $this );
foreach ($object as $key => &$value) {
if (empty($value) || empty($this->$key)) continue; // The object could be null from serialization?
if (is_object( $value )) {
try { $this->$key = @serialize( $value );
} catch (\Exception $e){ continue; } // Database object we need to catch the error thrown.
if ($_SESSION[__CLASS__][0] != 'O') continue;
} $onlyKeys[] = $key;
} return (isset($onlyKeys) ? $onlyKeys : null);
}
public function __destruct()
{ // We require a sleep function to be set manually for singleton to manage utilization
if (!defined( 'self::Singleton' ) || !self::Singleton) return null;
try { $_SESSION[__CLASS__] = @serialize( $this ); // I was using if (__sleep != null).. but resulted in errors, this is a shitty fix ill admit
} catch (\Exception $e){ unset($_SESSION[__CLASS__]); return null; };
if ($_SESSION[__CLASS__][0] != 'O') unset($_SESSION[__CLASS__]); // We only want to store objects, if
}
// The rest of the methods are for the sake of methods
public function &__get($variable)
{
return $GLOBALS[$variable];
}
public function __set($variable, $value)
{
$GLOBALS[$variable] = $value;
}
public function __isset($variable)
{
return array_key_exists( $variable, $GLOBALS );
}
public function __unset($variable)
{
unset($GLOBALS[$variable]);
}
public function __invoke()
{
return $this->storage;
}
private function set($name, $value = null)
{
$this->storage = null;
if ($value == null) {
if (is_array( $name )) $this->storage = $name;
else $this->storage[] = $name;
} else $this->storage[$name] = $value;
return $this;
}
private function get($variable = null)
{
return ($variable == null ?
$this->storage :
$this->{$variable});
}
private function has($variable)
{
return isset($this->$variable);
}
}
class stdOJB implements \ArrayAccess
{
use Singleton;
const Singleton = true; // turns on auto caching
public function __construct() {
return null;
}
public function offsetSet($offset, $value) {
if (is_null($offset)) $this->storage[] = $value;
else $this->storage[$offset] = $value;
}
public function offsetExists($offset) {
return isset($this->storage[$offset]);
}
public function offsetUnset($offset) {
unset($this->storage[$offset]);
}
public function offsetGet($offset) {
return isset($this->storage[$offset]) ? $this->storage[$offset] : null;
}
public function &__get($variable)
{
return $this->storage[$variable];
}
public function __set($variable, $value)
{
$this->storage[$variable] = $value;
}
public function __isset($variable)
{
return array_key_exists( $variable, $this->storage );
}
public function __unset($variable)
{
unset($this->storage[$variable]);
}
public function __destruct()
{
return null;
}
}
abstract class QuickFetch
{
protected $db;
public function fetch_into_current_class($array)
{
$object = get_object_vars( $this );
foreach ($array as $key => $value)
if (array_key_exists( $key, $object ))
$this->$key = $value;
}
public function fetch_as_object($sql,... $execute)
{
try {
$stmt = $this->db->prepare( $sql );
$stmt->setFetchMode( \PDO::FETCH_CLASS, Skeleton::class );
$stmt->execute( $execute );
$stmt = $stmt->fetchAll(); // user obj
return (is_array( $stmt ) && count( $stmt ) == 1 ?
array_pop( $stmt ) : $stmt);
} catch (\Exception $e) {
sortDump( $e );
}
}
}
class user extends QuickFetch {
use Singleton;
const Singleton = true;
public $info;
private function getPublicData()
{
if (!empty($this->courseId) && (!is_object( $this->course ) || $this->course->course_id != $this->courseI))
$this->course = (object) ['course_id' => 3]; // $this->fetch_as_object( $sql, $id );
var_dump($this->course);
exit(1);
if (!empty($this->boxColor)) {
if (!is_object( $this->course )) throw new \Error();
// $this->course->distance = $this->fetch_as_object( 'SELECT * FROM StatsCoach.golf_distance WHERE course_id = ? AND distance_color = ?', $this->courseId, $this->boxColor );
if (!isset($this->course->distance) || !is_object( $this->course->distance ) || $this->course->distance->distance_color != $this->boxColor) {
$this->course->distance = $this->fetch_as_object( 'SELECT * FROM StatsCoach.golf_distance WHERE course_id = ? AND distance_color = ?', $this->courseId, $this->boxColor );
return null;
}
if (!is_object( $this->course->distance )) throw new \Exception();
return null;
}
}
}
user::getPublicData();
Deprecated: Return type of stdOJB::offsetExists($offset) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /in/G2bVG on line 175
Deprecated: Return type of stdOJB::offsetGet($offset) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /in/G2bVG on line 183
Deprecated: Return type of stdOJB::offsetSet($offset, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /in/G2bVG on line 170
Deprecated: Return type of stdOJB::offsetUnset($offset) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /in/G2bVG on line 179
Warning: Undefined global variable $_SESSION in /in/G2bVG on line 28
Fatal error: Uncaught TypeError: array_key_exists(): Argument #2 ($array) must be of type array, null given in /in/G2bVG:28
Stack trace:
#0 /in/G2bVG(11): user::getInstance()
#1 /in/G2bVG(266): user::__callStatic('getPublicData', Array)
#2 {main}
thrown in /in/G2bVG on line 28
Process exited with code 255.
Output for 8.3.5
Warning: PHP Startup: Unable to load dynamic library 'sodium.so' (tried: /usr/lib/php/8.3.5/modules/sodium.so (libsodium.so.23: cannot open shared object file: No such file or directory), /usr/lib/php/8.3.5/modules/sodium.so.so (/usr/lib/php/8.3.5/modules/sodium.so.so: cannot open shared object file: No such file or directory)) in Unknown on line 0
Deprecated: Return type of stdOJB::offsetExists($offset) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /in/G2bVG on line 175
Deprecated: Return type of stdOJB::offsetGet($offset) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /in/G2bVG on line 183
Deprecated: Return type of stdOJB::offsetSet($offset, $value) should either be compatible with ArrayAccess::offsetSet(mixed $offset, mixed $value): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /in/G2bVG on line 170
Deprecated: Return type of stdOJB::offsetUnset($offset) should either be compatible with ArrayAccess::offsetUnset(mixed $offset): void, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /in/G2bVG on line 179
Warning: Undefined global variable $_SESSION in /in/G2bVG on line 28
Fatal error: Uncaught TypeError: array_key_exists(): Argument #2 ($array) must be of type array, null given in /in/G2bVG:28
Stack trace:
#0 /in/G2bVG(11): user::getInstance()
#1 /in/G2bVG(266): user::__callStatic('getPublicData', Array)
#2 {main}
thrown in /in/G2bVG on line 28
Process exited with code 255.
Output for 8.0.0 - 8.0.30
Warning: Undefined variable $_SESSION in /in/G2bVG on line 28
Fatal error: Uncaught TypeError: array_key_exists(): Argument #2 ($array) must be of type array, null given in /in/G2bVG:28
Stack trace:
#0 /in/G2bVG(11): user::getInstance()
#1 /in/G2bVG(266): user::__callStatic('getPublicData', Array)
#2 {main}
thrown in /in/G2bVG on line 28
Process exited with code 255.
Notice: Undefined variable: _SESSION in /in/G2bVG on line 28
Warning: array_key_exists() expects parameter 2 to be array, null given in /in/G2bVG on line 28
NULL
Process exited with code 1.
Output for 7.3.32 - 7.3.33
Warning: array_key_exists() expects parameter 2 to be array, null given in /in/G2bVG on line 28
NULL
Process exited with code 1.