Foros del Web » Programando para Internet » PHP »

unset heredando de ArrayIterator

Estas en el tema de unset heredando de ArrayIterator en el foro de PHP en Foros del Web. Muy buenas, os traigo algo realmente raro, o no lo logro entender o es un bug o algo raro, ahi voy: Código: <?php class Coleccion ...
  #1 (permalink)  
Antiguo 07/10/2011, 17:28
 
Fecha de Ingreso: octubre-2011
Mensajes: 37
Antigüedad: 12 años, 6 meses
Puntos: 9
unset heredando de ArrayIterator

Muy buenas, os traigo algo realmente raro, o no lo logro entender o es un bug o algo raro, ahi voy:

Código:
<?php

class Coleccion extends ArrayIterator
{
    
    public function clear()
    {
	foreach($this as $key => $value)
	    unset($this[$key]);
    }

}

$c = new Coleccion();
$c[] = 'valor1';
$c[] = 'valor2';
$c[] = 'valor...';

echo '<pre>', print_r($c), '</pre>';

/*
  esto imprime:
   Coleccion Object
   (
    [storage:ArrayIterator:private] => Array
        (
            [0] => valor1
            [1] => valor2
            [2] => valor...
        )

   )
   1
 */

$c->clear();

echo '<pre>', print_r($c), '</pre>';

/*
  esto imprime:
   Coleccion Object
   (
    [storage:ArrayIterator:private] => Array
        (
            [1] => valor2
        )

   )
   1
 */

/*
 * SOLUCION:
 * en el metodo clear(), contar elemetos, si aun hay, volver a limpiar
 * 
    public function clear()
    {
	foreach($this as $key => $value)
	    unset($this[$key]);
	if($this->count())
	    $this->clear();
    }
 
 */
es decir, clear no unsetea todos los elementos, sin embargo pasa por los indices, pero por alguna razon el indice 1, no lo unsetea, sabeis por que?, queda muy sucio volver a preguntar si aun hay elementos a count para volver a ejecutar la misma funcion....

PD: aclaro que heredo de ArrayIterator y no de ArrayObject, ya que el primero permite iterarse a si mismo, y el segundo segun he comprobado y leido en php.net itera sobre una copia de si mismo, por lo tanto en este caso concreto, en esta funcion clear, no podria modificar los valores o unsetearlos como es el caso... si podeis aclarar esto magnifico

saludos amigos y muchas gracias
  #2 (permalink)  
Antiguo 07/10/2011, 17:47
Avatar de andresdzphp
Colaborador
 
Fecha de Ingreso: julio-2011
Ubicación: $this->Colombia;
Mensajes: 2.749
Antigüedad: 12 años, 9 meses
Puntos: 793
Respuesta: unset heredando de ArrayIterator

Ese es un pequeño bug conocido ya, aquí encuentras otra alternativa. Un amigo lo reportó pero no se para cuando lo arreglen :D supongo que php 5.4.0

Código PHP:
Ver original
  1. To avoid this bug you can call offsetUnset in the for loop
  2.  
  3. <?php
  4. /*** ... ***/
  5. for ( $b->rewind(); $b->valid(); $b->offsetUnset( $b->key() ) )
  6. {
  7. /*** ... ***/
  8. ?>
  9.  
  10. Or unset it directly in the ArrayObject
  11. <?php
  12. /*** ... ***/
  13.     $a->offsetUnset( $b->key() );
  14. /*** ... ***/
  15. ?>
  16.  
  17. which will produce correct results

http://www.php.net/manual/es/arrayit...set.php#104789

Saludos.
__________________
Si sabemos como leer e interpretar el manual será mucho más fácil aprender PHP. En lugar de confiar en ejemplos o copiar y pegar - PHP
  #3 (permalink)  
Antiguo 07/10/2011, 18:06
 
Fecha de Ingreso: octubre-2011
Mensajes: 37
Antigüedad: 12 años, 6 meses
Puntos: 9
Respuesta: unset heredando de ArrayIterator

muchisimas gracias, eres un crack, pues bien para los interesados, asi quedaria el metodo clear

NOTA: ya no hereda de ArrayIterator, sino de ArrayObject, ya que con el metodo ArrayObject::getIterator() se puede acceder a el como se puede observar:

Código PHP:
    public function clear()
    {
    
$iterator $this->getIterator();

    for(
$iterator->rewind(); $iterator->valid(); $iterator->offsetUnset($iterator->key()))
        ;
    } 
aunque ahora me entra la duda del segundo metodo que plantea 'olav at fwt dot no' aqui:

Código PHP:
Or unset it directly in the ArrayObject
<?php
/*** ... ***/
    
$a->offsetUnset$b->key() );
/*** ... ***/
?>
como lo aplicariamos al metodo ahora que heredamos de ArrayObject? ya que sigo pensando que ese for sin instrucciones queda muy sucio... lo siento soy un poco friki.

PD: otra vez gracias al crack
  #4 (permalink)  
Antiguo 07/10/2011, 18:15
Avatar de andresdzphp
Colaborador
 
Fecha de Ingreso: julio-2011
Ubicación: $this->Colombia;
Mensajes: 2.749
Antigüedad: 12 años, 9 meses
Puntos: 793
Respuesta: unset heredando de ArrayIterator

Lo que propone ese tipo es destruirlo directamente con ArrayObject

Código PHP:
Ver original
  1. class Coleccion extends ArrayIterator
  2. {
  3. }
  4.  
  5. $c = new Coleccion();
  6. $x = new ArrayObject($c);
  7.  
  8. $c[] = 'valor1';
  9. $c[] = 'valor2';
  10. $c[] = 'valor...';
  11.  
  12. foreach ($c as $k => $v) {
  13.     $x->offsetunset($k);
  14. }
  15.  
  16. echo '<pre>', print_r($c), '</pre>';
__________________
Si sabemos como leer e interpretar el manual será mucho más fácil aprender PHP. En lugar de confiar en ejemplos o copiar y pegar - PHP
  #5 (permalink)  
Antiguo 07/10/2011, 18:20
 
Fecha de Ingreso: octubre-2011
Mensajes: 37
Antigüedad: 12 años, 6 meses
Puntos: 9
Respuesta: unset heredando de ArrayIterator

si, pero suponiendo que ahora en vez de heredar de ArrayIterator, heredamos de ArrayObject
  #6 (permalink)  
Antiguo 07/10/2011, 18:24
 
Fecha de Ingreso: octubre-2011
Mensajes: 37
Antigüedad: 12 años, 6 meses
Puntos: 9
Respuesta: unset heredando de ArrayIterator

Código PHP:
class Coleccion extends ArrayObject
{
    
    public function 
clear()
    {
    
$iterator $this->getIterator();

    foreach(
$iterator as $key => $value)
        
$this->offsetUnset($key);
    }


resultado:

NOTICE Coleccion::clear(): ArrayIterator::next(): Array was modified outside object and internal position is no longer valid
  #7 (permalink)  
Antiguo 07/10/2011, 18:31
Avatar de andresdzphp
Colaborador
 
Fecha de Ingreso: julio-2011
Ubicación: $this->Colombia;
Mensajes: 2.749
Antigüedad: 12 años, 9 meses
Puntos: 793
Respuesta: unset heredando de ArrayIterator

Usando exchangeArray se soluciona ese error, pero sinceramente no sé si es la mejor forma de hacerlo:

Código PHP:
Ver original
  1. class Coleccion extends ArrayObject
  2. {
  3.     public function clear() {
  4.         $this->exchangeArray($this);
  5.         foreach ($this as $k => $v) {
  6.             $this->offsetUnset($k);
  7.         }
  8.     }
  9. }
  10.  
  11. $c = new Coleccion();
  12.  
  13. $c[] = 'valor1';
  14. $c[] = 'valor2';
  15. $c[] = 'valor...';
  16.  
  17. $c->clear();
  18.  
  19. echo '<pre>', print_r($c, true), '</pre>';
__________________
Si sabemos como leer e interpretar el manual será mucho más fácil aprender PHP. En lugar de confiar en ejemplos o copiar y pegar - PHP
  #8 (permalink)  
Antiguo 07/10/2011, 18:41
 
Fecha de Ingreso: octubre-2011
Mensajes: 37
Antigüedad: 12 años, 6 meses
Puntos: 9
Respuesta: unset heredando de ArrayIterator

muy grande, muy bueno, muchas gracias, yo tampoco se si sera la mejor manera, pero desde luego es la mas limpia, aunque cuidado con esta clase y las interfaces que implementa, en concreto este metodo, ArrayObject::exchangeArray() ya que simplemente observarlo:

http://www.php.net/manual/es/arrayobject.exchangearray.php

tenemos en las contribuciones de los usuarios que recibe la referencia del array y al cambiar algo en el array referenciado nos lo cambiará en el mismo, en nuestro caso no hay ningun problema ya que el array es $this, pero para confirmarlo, tenemos esta nota de Dmitri

Código:
It seems that input array is always passed by reference.
For example if you have an existing array
$array with some values
then you have an arrayobject $o
and then you do this:

$o->exchangeArray($array);
$o->offsetSet('somekey', 'some value');

Now if you check your $array array, it will have
a key 'somekey' with value of 'some value'

I totally did not expect that, I am sure it was a mistake to pass array by reference by default.
  #9 (permalink)  
Antiguo 07/10/2011, 18:48
Avatar de andresdzphp
Colaborador
 
Fecha de Ingreso: julio-2011
Ubicación: $this->Colombia;
Mensajes: 2.749
Antigüedad: 12 años, 9 meses
Puntos: 793
Respuesta: unset heredando de ArrayIterator

Si es cierto, hay que tener cuidado con eso. Aunque a mi no se me pasa el valor... Quien sabe si lo solucionaron, estoy usando PHP 5.3.8

Código PHP:
Ver original
  1. <?php
  2. $array = array(1,2,3);
  3. $o = new ArrayObject();
  4.  
  5. $o->exchangeArray($array);
  6. $o->offsetSet('somekey', 'some value');
  7.  
  8. echo '<pre>';
  9. print_r($array);
  10. print_r($o);
  11. echo '</pre>';
__________________
Si sabemos como leer e interpretar el manual será mucho más fácil aprender PHP. En lugar de confiar en ejemplos o copiar y pegar - PHP
  #10 (permalink)  
Antiguo 07/10/2011, 19:03
 
Fecha de Ingreso: octubre-2011
Mensajes: 37
Antigüedad: 12 años, 6 meses
Puntos: 9
Respuesta: unset heredando de ArrayIterator

buena idea, voy a intentar actualizar php, no tengo ni idea que version exacta estoy usando, el tema es que llevo 2 meses inmerso en linux, ubuntu concretamente y seguramente en pocos dias debian, asi que a buscar comandos:

-para saber la version de php
Código PHP:
<?php

phpinfo
();
-para actualizar en caso de no estar a la ultima

en cuanto los encuentre los posteo para los que lean el post posteriormente y por seguir el contexto quieran tambien actualizar php en sistemas basados en debian, como en mi caso, ubuntu

Etiquetas: arrayiterator, arrayobject, bug, exchangearray, offsetunset, unset
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta

SíEste tema le ha gustado a 1 personas




La zona horaria es GMT -6. Ahora son las 22:58.