[Class] Problème d'itérateurs

Mammouth du PHP | 1668 Messages

05 juil. 2008, 12:00

Bonjours à toutes et tous,

Je vais faire deux topic, car j'ai deux problèmes pour une class, pour tenté de respecter la règle du forum...
Voilà, j'ai une class de gestion de cache qui à pour parent Itertor, seulement, voilà mon proble, il saute systèmatiquement le premier couple clef/valeur, exemple :

Si je fais ça :
<?php
include("Kache.php");
$cache=new Kache("test");
$tableau=array("ligne 1", "ligne 2", "ligne 3", "ligne 4", "ligne 5");
$cache->genere($tableau, false);

echo "<p><p><p>Test 2 :</p>";
foreach ($cache as $valeur) {
	echo "<p>".$valeur."</p>";
}
Ca m'affiche :
Test 2 :
ligne 2
ligne 3
ligne 4
ligne 5
Et si je fais :
$cache->detruit(true);
$tableau2=array("clef 1" => "ligne 1", "clef 2" => "ligne 2", "clef 3" => "ligne 3", "clef 4" => "ligne 4", "clef 5" => "ligne 5");
$cache->genere($tableau, false);
echo "<p><p><p>Test 3 :</p>";
foreach ($cache as $clef => $valeur) {
	echo "<p><b>[".$clef."]</b> - ".$valeur."</p>";
}
J'ai ça :
[1] - ligne 2
[2] - ligne 3
[3] - ligne 4
[4] - ligne 5
Voilà un bout de ma class :
<?php
class Kache implements Iterator {
//...
	// Variables pour les fonctions itératrices
	private $clef=array();// Les clefs

	private $valeur=array();// Les valeurs

	private $index=0; // L'index
//...
	public function genere($contenu=NULL, $existe=true)
	{
		$existe=(bool) $existe;

		if (!$existe) {
			if(!empty($contenu)){
				$this->cache=$contenu;
			}
			else {
				die("Veuillez stipuler un contenu");
			}
		}
		else {
			if(!empty($contenu)){
				$this->cache=$contenu;
			}
			else {
				die("Veuillez stipuler un contenu");
			}
		}

		$this->test_tableau();

		// utilisation de serialize() pour transformer $content en chaine de caractères
		$contenu_serialize = serialize($this->cache);

		// échappement les caractères spéciaux pour pouvoir mettre le tout entre quotes dans le futur fichier
		$contenu_serialize = str_replace(array('', "'", "0"), array('\\', '\'', '0'), $contenu_serialize);

		// création du code php à stocker dans le fichier
		$contenu_serialize = "<?php" . "\n" . '$cache = unserialize("' .  $contenu_serialize . '");' . "\n" . '?>';

		// écriture du code dans le fichier
		$fichier = fopen($this->chemin_cache.$this->nom.$this->extention, 'w');
		$resultat = fwrite($fichier, $contenu_serialize);
		fclose($fichier);

		// renvoie true si l'écriture du fichier a réussi
		return $resultat;
	}
//...
	private function test_tableau(){
		if(is_array($this->cache)){
			foreach ($this->cache as $clef => $valeur) {
				$this->clef[]=$clef;
				$this->valeur[]=$valeur;
			}
			return true;
		}
		return false;
	}

	// Les fonctions Itératrices (pour les boucles)
	public function current(){
		return $this->valeur[$this->index];
	}

	public function next(){
		$this->index+1;
	}

	public function valid(){
		return ($this->index++ < (count($this->clef)-1));
                                // si je fais return ($this->index++ <= count($this->clef));
                                // J'ai deux ligne de trop au test 3 du tyle [0] - 
	}

	public function key(){
		return $this->clef[$this->index];
	}

	public function rewind(){
		$this->index=0;
	}

}

?>
Voilà, mes tapleaux sont bon pourtant...

Par avance merci de votre aide...
"À ceux qui poursuivent leurs rêves et se spécialisent dans l'impossible" Joseph Kong

10 ans de PHP, déjà.

"moi jtrouve que katagoto il déchire!" Nagol

ViPHP
ViPHP | 5924 Messages

05 juil. 2008, 13:34

C'est sur next que tu dois fait l'incrémentation, pas sur valid amha.

Mammouth du PHP | 1668 Messages

05 juil. 2008, 14:19

Sur PHP5 avancé seconde édition y a écrit :
return (this->index +1 <= count($this->login)) ;
Donc moi, en adaptant un peut j'arrive à ça :
return ($this->index +1 <= count($this->valeur));
Mais, même en essayant
return ($this->index +1 <= count($this->valeur));
ou
return (($this->index +1) <= count($this->valeur));
ou avec clefs, j'ai ce message d'erreur :
Fatal error: Maximum execution time of 30 seconds exceeded in D:\wamp\www\test\test_kache.php on line 19
Avec ligne 1 répété des 100aine de fois

Or, ce n'est que ça :
<?php
foreach ($cache as $valeur) {
	echo "<p>".$valeur."</p>";
}//l.19
"À ceux qui poursuivent leurs rêves et se spécialisent dans l'impossible" Joseph Kong

10 ans de PHP, déjà.

"moi jtrouve que katagoto il déchire!" Nagol

Modérateur PHPfrance
Modérateur PHPfrance | 2575 Messages

05 juil. 2008, 14:51

Le problème est dans l'index de départ par rapport à la première lecture. Par défaut l'index est à 0 et l'itération fait systématiquement un next (index +1) avant de lire. C'est pourquoi ton tableau commence toujours par la deuxième case au lieu de la première.

Voici une adaptation que j'ai faite de ton code :
<?php
class Cache implements Iterator {
	//
	function Cache($fichier="cache.txt"){
		$this->fichier = $fichier;
	}
    // Variables pour les fonctions itératrices
    private $clef = array();// Les clefs

    private $valeur = array();// Les valeurs

    private $index = 0; // L'index
	
	private $fichier; // Fichier cache
	
//
    public function genere($contenu=null, $existe=true)
    {
        $existe=(bool) $existe;

        if (!$existe) {
            if(!empty($contenu)){
                $this->cache=$contenu;
            }
            else {
                die("Veuillez stipuler un contenu");
            }
        }
        else {
            if(!empty($contenu)){
                $this->cache=$contenu;
            }
            else {
                die("Veuillez stipuler un contenu");
            }
        }

        $this->test_tableau();

        // utilisation de serialize() pour transformer $content en chaine de caractères
        $contenu_serialize = serialize($this->cache);

        // échappement les caractères spéciaux pour pouvoir mettre le tout entre quotes dans le futur fichier
        $contenu_serialize = str_replace(array('"', "'"), array("\\\"", "\\'"), $contenu_serialize);

        // création du code php à stocker dans le fichier
        $contenu_serialize = "<?php \n" . "\$cache = unserialize(\"" .  $contenu_serialize . "\"); \n ?>";

        // écriture du code dans le fichier
        $resultat = file_put_contents($this->fichier, $contenu_serialize);

        // renvoie true si l'écriture du fichier a réussi
        return $resultat;
    }
//...
    private function test_tableau(){
        if(is_array($this->cache)){
            foreach ($this->cache as $clef => $valeur) {
                $this->clef[]=$clef;
                $this->valeur[]=$valeur;
            }
            return true;
        }
        return false;
    }
	
    // Les fonctions Itératrices (pour les boucles)
    public function current(){
        if ($this->valid()) return $this->valeur[$this->index]; else return null;
    }
    public function next(){
		$this->index++;
        if ($this->valid()) return true; else return false;
    }
	public function valid(){
		return ($this->index >= 0 && $this->index < count($this->clef));
	}
    public function previous(){
		$this->index--;
        if ($this->valid()) return true; else return false;
    }
    public function key(){
        if ($this->valid()) return $this->clef[$this->index];
    }
    public function rewind(){
        $this->index=0;
    }
}
//
$cache = new Cache();
$tableau1 = array("ligne 1", "ligne 2", "ligne 3", "ligne 4", "ligne 5");
$cache->genere($tableau1, false);
//
echo "<p><p><p>Test 1 :</p>";
while ($cache->valid()) {
    echo "<p>".$cache->current()."</p>";
	$cache->next();
}
//
$tableau2 = array("clef 1" => "ligne 1", "clef 2" => "ligne 2", "clef 3" => "ligne 3", "clef 4" => "ligne 4", "clef 5" => "ligne 5");
$cache->genere($tableau2, false);
//
echo "<p><p><p>Test 2 :</p>";
while ($cache->valid()) {
    echo "<p>".$cache->current()."</p>";
	$cache->next();
} 
?> 
--------//////----//---//----//////
-------//---//----//---//----//---//
------//////----//////-----//////
-----||--------||--||---||
Prendre le recul n'est pas une perte de temps.


ps: Affrontez moi dans l'arène

Mammouth du PHP | 1668 Messages

05 juil. 2008, 15:19

Merci sadeq, ça marche niquel :lol:

J'ai bien pensé que ça venait du fait que ça faisait next dès le début, mais je sne savais pas comment le résourde...
"À ceux qui poursuivent leurs rêves et se spécialisent dans l'impossible" Joseph Kong

10 ans de PHP, déjà.

"moi jtrouve que katagoto il déchire!" Nagol