I needed to merge SplObjectStorages.
<?php
// As an object set
$SplObjectStorage_1 = new SplObjectStorage();
$object1 = new StdClass;
$object1->attr = 'obj 1';
$object2 = new StdClass;
$object2->attr = 'obj 2';
$object3 = new StdClass;
$object3->attr = 'obj 3';
$SplObjectStorage_1->attach($object1);
$SplObjectStorage_1->attach($object2);
$SplObjectStorage_1->attach($object3);
// Another one object set
$SplObjectStorage_2 = new SplObjectStorage();
$object4 = new StdClass;
$object4->attr = 'obj 4';
$object5 = new StdClass;
$object5->attr = 'obj 5';
$object6 = new StdClass;
$object6->attr = 'obj 6';
$SplObjectStorage_2->attach($object4);
$SplObjectStorage_2->attach($object5);
$SplObjectStorage_2->attach($object6);
/**
* Merge SplObjectStorage
*
* @param how many SplObjectStorage params as you want
* @return SplObjectStorage
*/
function mergeSplObjectStorage() {
$buffer = new SplObjectStorage();
if( func_num_args() > 0 ) {
$args = func_get_args();
foreach ($args as $objectStorage) {
foreach($objectStorage as $object) {
if(is_object( $object ) ) {
$buffer->attach($object);
}
}
}
}
else{
return FALSE;
}
return $buffer;
}
$merge = mergeSplObjectStorage($SplObjectStorage_1, $SplObjectStorage_2);
?>
<?php
echo $merge->count();
?>
Will output :
6
<?php
$merge->rewind();
while($merge->valid()) {
$object = $merge->current();
var_dump($object);
$merge->next();
}
?>
Will ouput :
object(stdClass)#2 (1) {
["attr"]=>
string(5) "obj 1"
}
object(stdClass)#3 (1) {
["attr"]=>
string(5) "obj 2"
}
object(stdClass)#4 (1) {
["attr"]=>
string(5) "obj 3"
}
object(stdClass)#6 (1) {
["attr"]=>
string(5) "obj 4"
}
object(stdClass)#7 (1) {
["attr"]=>
string(5) "obj 5"
}
object(stdClass)#8 (1) {
["attr"]=>
string(5) "obj 6"
}
My two cents.
La clase SplObjectStorage
(PHP 5 >= 5.3.0)
Introducción
La clase SplObjectStorage proporciona un mapa a partir de objetos de datos, o datos ignorados de un grupo de objetos. Este doble objetivo puede ser útil en muchos casos relacionados con la necesidad de identificar de forma única los objetos.
Sinopsis de la Clase
/* Métodos */
}Ejemplos
Ejemplo #1 SplObjectStorage como un grupo
<?php
// Como un grupo de objetos
$s = new SplObjectStorage();
$o1 = new StdClass;
$o2 = new StdClass;
$o3 = new StdClass;
$s->attach($o1);
$s->attach($o2);
var_dump($s->contains($o1));
var_dump($s->contains($o2));
var_dump($s->contains($o3));
$s->detach($o2);
var_dump($s->contains($o1));
var_dump($s->contains($o2));
var_dump($s->contains($o3));
?>
El resultado del ejemplo sería:
bool(true) bool(true) bool(false) bool(true) bool(false) bool(false)
Ejemplo #2 SplObjectStorage como un mapa
<?php
// Como un mapa de objetos de datos
$s = new SplObjectStorage();
$o1 = new StdClass;
$o2 = new StdClass;
$o3 = new StdClass;
$s[$o1] = "data for object 1";
$s[$o2] = array(1,2,3);
if (isset($s[$o2])) {
var_dump($s[$o2]);
}
?>
El resultado del ejemplo sería:
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
Tabla de contenidos
- SplObjectStorage::addAll — Agrega todos los objetos de otro almacenamiento
- SplObjectStorage::attach — Agrega un objeto en el almacenamiento
- SplObjectStorage::contains — Comprueba si el almacenamiento contiene un objeto específico
- SplObjectStorage::count — Devuelve el número de objetos en el almacenamiento
- SplObjectStorage::current — Devuelve la entrada actual de almacenamiento
- SplObjectStorage::detach — Quita un object de el almacenamiento
- SplObjectStorage::getHash — Calcular un identificador único (hash) para los objetos contenidos
- SplObjectStorage::getInfo — Devuelve los datos asociados con la entrada del iterador actual
- SplObjectStorage::key — Devuelve el índice en el que se encuentra el iterador actualmente
- SplObjectStorage::next — Mover a la siguiente entrada
- SplObjectStorage::offsetExists — Comprueba si un objeto existe en el almacenamiento
- SplObjectStorage::offsetGet — Devuelve los datos asociados con un object
- SplObjectStorage::offsetSet — Asocia datos a un objeto en el almacenamiento
- SplObjectStorage::offsetUnset — Quita un objeto de el almacenamiento
- SplObjectStorage::removeAll — Remover objetos contenidos en otro almacenamiento de el almacenamiento actual
- SplObjectStorage::removeAllExcept — Remover objetos excepto los contenidos en otro almacenamiento del almacenamiento actual
- SplObjectStorage::rewind — Rebobina el iterador a el primer elemento de el almacenamiento
- SplObjectStorage::serialize — Serializa el almacenamiento
- SplObjectStorage::setInfo — Establece los datos asociados con el iterador de la entrada actual
- SplObjectStorage::unserialize — Deserializa un almacenamiento desde su representación string
- SplObjectStorage::valid — Comprobar si la entrada actual del iterador es válida
inwebo at gmail dot fr ¶
1 year ago
Jan Walther ¶
1 year ago
I rewrote some scripts and changed object storage with arrays to SplObjectStorage. At some point I needed support of array_rand() but I did not find a function to return a random attached object of an SplObjectStorage object.
So here is my solution for random access to SplObjectStorage:
<?php
$o1 = new StdClass;
$o2 = new StdClass;
$s = new SplObjectStorage;
$s->attach($o1);
$s->attach($o2);
$random = rand(0,$s->count()-1);
$s->rewind();
for($i=0;$i<$random;$i++) {
$s->next();
}
var_dump($s->current());
?>
Robertas at pobox com ¶
3 years ago
PHP 5.2.x and lower doesn't implement ArrayAccess in SplObjectStorage - it is only implemented starting from PHP 5.3
randallgirard at hotmail dot com ¶
3 years ago
I have two things to note about SplObjectStorage:
#1: A reference to the object itself is stored (not just a hash to compare against the object) and it must be removed before the object is destroyed and the destructor is executed.
#2: SplObjectStorage::rewind() MUST be called to initiate the iterator and before SplObjectStorage::current() will return an object (and I think the only way to retrieve an object?) rather than automatically starting at the first element as I expected it to, like an array for example. This assumption is based on SplObjectStorage::current() returning NULL until SplObjectStorage::rewind() is called once the objects are contained. As a note, always use REWIND before iterating through or fetching objects.
<?php
class foo {
public function __destruct() {
print("--- DESTRUCTOR FIRED!!<br />\r\n");
}
}
# Create object and storage
$bar = new foo();
$s = new SplObjectStorage();
# Rewind early just as a test
$s->rewind();
# attach the object
$s->attach($bar, array('test'));
# Unset the object; destructor does NOT fire
unset($bar);
print("Object has been unset<br />\r\n");
# First demonstrate that REWIND must be called to initialize the iterator
$obj = $s->current();
var_dump($obj);
print("- Note the NULL (from \$s->current())<br />\r\n");
# Initialize, and then detach the current (and only) object
$s->rewind();
$s->detach( $s->current() );
# The destructor should NOW execute
?>
Output:
Object has been unset
NULL - Note the NULL (from $s->current())
--- DESTRUCTOR FIRED!!
Hayley Watson ¶
1 year ago
As an iterator, SplObjectStorage traverses the _keys_ of the map (the $o1, $o2 of Example 2) rather than the values. To retrieve each of those in turn requires an additional lookup:
<?php
// As a map from objects to data
$s = new SplObjectStorage();
$o1 = (object)array('a'=>1);
$o2 = (object)array('b'=>2);
$o3 = (object)array('c'=>3);
$s[$o1] = "data for object 1";
$s[$o2] = array(1,2,3);
foreach($s as $i => $key)
{
echo "Entry $i:\n"; // You get a numeric index
var_dump($key, $s[$key]);
echo "\n";
}
?>
This makes sense when you use an SplObjectStorage as a set, since in that case all of the "values" are null.
