1

I have a PHP Class which requires a unique value in its constructor. If multiple instances of the same class are passed the same value the results are horrific.

How would I go about detecting other instances of a Class so I can check and prevent this from happening before constructing any new ones?

George Reith
  • 13,132
  • 18
  • 79
  • 148
  • Possible duplicate of http://stackoverflow.com/questions/475569/get-all-instances-of-a-class-in-php – kba Jan 06 '12 at 14:55

2 Answers2

4

A simple solution would be to keep a static array of the values inside the class. Then, when a new instance is created, check the static array's contents in the constructor.

Something like..

class Foo {
    private static $usedValues = array();

    public function __construct($val) {
        if(in_array($val, self::$usedValues)) {
            throw new Exception('blah');
        }

        self::$usedValues[] = $val;
    }
}
Jani Hartikainen
  • 42,745
  • 10
  • 68
  • 86
  • +1 I was just about to write the same thing. [Here's another implementation example](http://stackoverflow.com/a/475613/453331). – kba Jan 06 '12 at 14:54
  • So simple yet so clever, thanks! I knew static existed for a reason :D – George Reith Jan 06 '12 at 15:05
2

I think the multiton pattern is right for you.

class Foo {
    static protected $_instances = array();
    static public function getInstance($id) {
        if(!self::exists($id)) {
            self::$_instances[$id] = new Foo($id);
        }
        return self::$_instances[$id];
    }
    static public function exists($id) {
        return isset(self::$_instances[$id]);
    }
    protected function __construct($id) {
    }
}
Rudolph Gottesheim
  • 1,671
  • 1
  • 17
  • 30
  • @MarkBaker, @Rudolph, I don't think this is actually a correct answer. First of all, shouldn't `$_instances` be static? Second, it seems that OP wants to know if an instance already exists with that ID - not just retrieve it if it exists. – kba Jan 06 '12 at 15:03
  • Thank, I just spotted that error myself and corrected it. I'm guessing that what I wrote is what he really needs, but a `static public exists($id)` method is written pretty easily. – Rudolph Gottesheim Jan 06 '12 at 15:06
  • Thanks, this pattern is interesting me. But I am confused because the outcome seems to be `new Foo($id)` but if this is called in the constructor then doesn't this recreate an instance of itself and attempt to check it again? Seems kind of wasteful to run the script twice and construct two instances to perform this check, unless I am mistaken? – George Reith Jan 06 '12 at 15:25
  • @GEorge, no it doesn't create two instances, because the getInstance() method is called statically.... static calls (and that includes the exists() method as well) don't create a new instance unless explicitly via "new" – Mark Baker Jan 06 '12 at 15:30
  • It isn't called in the constructor. The custructor is deliberately left empty and set to protected/private so it can only be called from within the class - `getInstance()`. – Rudolph Gottesheim Jan 06 '12 at 15:31
  • @RudolphGottesheim but you would have to call this within the constructor to ensure that the class isn't constructed before it checks whether it is allowed no? Or do you mean I have to explicitly call this function before creating a new Instance? – George Reith Jan 06 '12 at 15:37
  • What I described there is the so-called 'factory pattern'. It's used to make sure no one can create an instance of that class directly. (By setting the constructor to protected or private.) The only way you can create an instance is by calling the static method getInstance(), which does the appropriate check(s) for you. – Rudolph Gottesheim Jan 06 '12 at 15:42