SplObjectStorage не работает со строкой, что делать? - PullRequest
7 голосов
/ 01 октября 2009

Кто-то предложил использовать SplObjectStorage для отслеживания набора уникальных вещей. Отлично, только он не работает со строками. В сообщении об ошибке «SplObjectStorage :: attach () ожидает, что параметр 1 будет объектом, строка указана в fback.php в строке 59»

Есть идеи?

Ответы [ 5 ]

8 голосов
/ 01 октября 2009

SplObjectStorage - это то, что говорит его название: класс хранения для хранения объектов. В отличие от некоторых других языков программирования strings не являются объектами в PHP, они, ну, в общем, строки ;-). Поэтому нет смысла хранить строки в SplObjectStorage - даже если вы оберните свои строки в объект класса stdClass.

Лучший способ сохранить коллекцию уникальных строк si для использования массивов (в качестве хеш-таблиц) со строкой в ​​качестве ключа и значением (как предложено Ian Selby ).

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

Однако вы можете обернуть эту функцию в пользовательский класс:

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;
    }

    // ... 
}

Кстати, вы можете смоделировать поведение SplObjectStorage для PHP <5.3.0 и лучше понять, что он делает. </p>

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

SplObjectStorage сохраняет уникальный хэш для каждого экземпляра (например, spl_object_hash()) для быть в состоянии идентифицировать экземпляры объекта. Как я уже говорил выше: строка вообще не является объектом, поэтому она не имеет хэша экземпляра. Уникальность строки можно проверить путем сравнения строковых значений - две строки равны, если они содержат одинаковый набор байтов.

5 голосов
/ 26 декабря 2009

Это Объект Хранилище. Строка - это скаляр . Так что используйте SplString .

1 голос
/ 01 октября 2009

Обернуть строку в stdClass?

$dummy_object = new stdClass();
$dummy_object->string = $whatever_string_needs_to_be_tracked;
$splobjectstorage->attach($dummy_object);

Однако каждый объект, созданный таким образом, все равно будет уникальным, даже если строки идентичны.

Если вам нужно беспокоиться о дублирующих строках, возможно, вам следует использовать вместо этого хеш (ассоциативный массив) для отслеживания их?

0 голосов
/ 09 октября 2013

Или, может быть, просто создать экземпляр вашей строки как объекта с помощью метода __toString () - таким образом, вы можете иметь их оба - объект и возможность использовать его как строку (var_dump, echo) ..

0 голосов
/ 01 октября 2009
$myStrings = array();
$myStrings[] = 'string1';
$myStrings[] = 'string2';
...

foreach ($myStrings as $string)
{
    // do stuff with your string here...
}

Если вы хотите обеспечить уникальность строк в массиве, вы можете сделать пару вещей ... во-первых, просто использовать array_unique (). Это, или вы можете создать ассоциативный массив со строками в качестве ключей, а также со значениями:

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

Если вы хотите быть объектно-ориентированными по этому поводу, вы можете сделать что-то вроде:

class StringStore
{
   public static $strings = array();

   // helper functions, etc.  You could also make the above protected static and write public functions that add things to the array or whatever
}

Затем в своем коде вы можете делать такие вещи, как:

StringStore::$strings[] = 'string1';
...

И повторять так же:

foreach (StringStore::$strings as $string)
{
    // whatever
}

SplObjectStorage предназначен для отслеживания уникальных экземпляров Объектов, и если вы не работаете со строками, это немного излишне для того, чего вы пытаетесь достичь (на мой взгляд).

Надеюсь, это поможет!

...