Search code examples
phpspl

SplObjectStorage doesn't work with String, what to do?


Someone has suggested to e to use SplObjectStorage to keep track of a set of unique things. Great, except it doesn't work with strings. An error says " SplObjectStorage::attach() expects parameter 1 to be object, string given in fback.php on line 59"

Any ideas?


Solution

  • The SplObjectStorage is what its name says: a storage class for storing objects. In contrast to some other programming languages strings are not objects in PHP, they are, well, strings ;-). It therefore makes no sense to store strings in a SplObjectStorage - even if you wrap your strings in an object of class stdClass.

    The best way to store a collection of unique strings si to use arrays (as hashtables) with the string as the key as well as the value (as suggested by Ian Selby).

    $myStrings = array();
    $myStrings['string1'] = 'string1';
    $myStrings['string2'] = 'string2';
    // ...
    

    You could however wrap this functionality into a custom class:

    class UniqueStringStorage // perhaps implement Iterator
    {
        protected $_strings = array();
    
        public function add($string)
        {
            if (!array_key_exists($string, $this->_strings)) {
                $this->_strings[$string] = $string;
            } else {
                //.. handle error condition "adding same string twice", e.g. throw exception
            }
            return $this;
        }
    
        public function toArray()
        {
            return $this->_strings;
        }
    
        // ... 
    }
    

    By the way you san simulate the behavior of SplObjectStorage for PHP < 5.3.0 and to get a better understanding of what it does.

    $ob1 = new stdClass();
    $id1 = spl_object_hash($ob1);
    $ob2 = new stdClass();
    $id2 = spl_object_hash($ob2);
    $objects = array(
        $id1 => $ob1,
        $id2 => $ob2
    );
    

    SplObjectStorage stores a unique hash for each instance (like spl_object_hash()) to be able to identify object instances. As I said above: a string is not an object at all, it therefore does not have an instance hash. A string's uniqueness can be checked by comparing the string values - two strings are equal when they contain the same set of bytes.