I'm with @Jeff, it's a bit unclear what you are trying to do. You can replace array_key_exists()
with in_array()
, and check if the new instance is contained in the $instances
array (obviously not the same, but one with the same properties, which is why we don't use a strict comparison in in_array()
).
Then, you can save all the instances with different parameters in your cache, and as soon as you find one in the array, just return it.
<?php
class SingleInstance
{
private static $instances = [];
public static function load($class, $args = null)
{
if ($args) {
$args = implode(', ', $args);
}
$c = new $class($args);
if (in_array($c, self::$instances)) {
echo "Hit!";
return self::$instances[$class];
}
self::$instances[$class] = $c;
return self::$instances[$class];
}
}
class Words
{
private $word;
public function __construct($word) {
$this->word = $word;
}
public function show() {
return $this->word;
}
}
$a = SingleInstance::load('Words', ['Dog']);
echo $a->show().PHP_EOL;
$b = SingleInstance::load('Words', ['Cat']);
echo $b->show().PHP_EOL;
$c = SingleInstance::load('Words', ['Cat']);
echo $c->show().PHP_EOL;
Demo
The downside to this is that you're trying to do some kind of cache, it's worthless since you're instantiating the class anyway in order to test if you already have it.
If this is some kind of cache, then you can give it a try computing a checksum of the class' name and arguments and using that as a key (in this case you can keep your initial array_key_exists()
call):
<?php
class SingleInstance
{
private static $instances = [];
public static function load($class, $args = null)
{
if ($args) {
$args = implode(', ', $args);
}
$checksum = md5($class.$args);
if (array_key_exists($checksum, self::$instances)) {
echo "Hit!";
return self::$instances[$checksum];
}
self::$instances[$checksum] = new $class($args);
return self::$instances[$checksum];
}
}
class Words
{
private $word;
public function __construct($word) {
$this->word = $word;
}
public function show() {
return $this->word;
}
}
$a = SingleInstance::load('Words', ['Dog']);
echo $a->show().PHP_EOL;
$b = SingleInstance::load('Words', ['Cat']);
echo $b->show().PHP_EOL;
$c = SingleInstance::load('Words', ['Cat']);
echo $c->show().PHP_EOL;
Demo
And about your first question in the comments, this code works with just one argument, but it will break with more. To fix this, use argument unpacking:
<?php
class SingleInstance
{
private static $instances = [];
public static function load($class, $args = null)
{
$checksum = md5($class.implode(', ', $args));
if (array_key_exists($checksum, self::$instances)) {
echo "Hit!";
return self::$instances[$checksum];
}
self::$instances[$checksum] = new $class(... $args); // argument unpacking
return self::$instances[$checksum];
}
}
class Words
{
private $word;
private $word2;
public function __construct($word, $word2) {
$this->word = $word;
$this->word2 = $word2;
}
public function show() {
return $this->word." ".$this->word2;
}
}
$a = SingleInstance::load('Words', ['Dog', 'Word1']);
echo $a->show().PHP_EOL;
$b = SingleInstance::load('Words', ['Cat', 'Word2']);
echo $b->show().PHP_EOL;
$c = SingleInstance::load('Words', ['Cat', 'Word2']);
echo $c->show().PHP_EOL;
Demo