[PHP5] SMARTDIR : LES ITÉRATEURS EN PHP - LECTURE INTELLIGENTE DE RÉPERTOIRE

kankrelune Messages postés 1293 Date d'inscription mardi 9 novembre 2004 Statut Membre Dernière intervention 21 mai 2015 - 20 nov. 2006 à 13:05
mkaffel Messages postés 3 Date d'inscription jeudi 27 juillet 2006 Statut Membre Dernière intervention 2 octobre 2007 - 12 déc. 2007 à 09:37
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/40393-php5-smartdir-les-iterateurs-en-php-lecture-intelligente-de-repertoire

mkaffel Messages postés 3 Date d'inscription jeudi 27 juillet 2006 Statut Membre Dernière intervention 2 octobre 2007
12 déc. 2007 à 09:37
Merci de ta réponse,

pour le moment je suis capable de récupérer la liste des fichiers se trrouvant direcetement dans ce répertoire(pas de recherche dans les sous dossiers en clair), mais mon besoin est différent je voudrais récupérer tous les fichiers depuis le répertoire que je spécifie (avec recherche dans les sous-dossiers donc)

Je voudrais donc savoir comment faire pour avoir une liste de tous les fichiers

merci encore
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
11 déc. 2007 à 19:53
Hello,
déjà merci:-)
Ensuite, je mets désormais la licence de mes codes, tellement cette question m'a été posée :-) Donc : LGPL.

Enfin...il ne devrait pas y avoir de problème particulièer quant à la racine du répertoire lu. Quand tu dis "je n'arrive pas à avoir une liste complète des fichiers uniquement depuis le répertoire source (en clair si mon répertoire source est C:\, je veux tous les fichiers de mon disque dur)", que vois tu au juste ? Tu en vois juste une partie? Tu ne vois rien ?
mkaffel Messages postés 3 Date d'inscription jeudi 27 juillet 2006 Statut Membre Dernière intervention 2 octobre 2007
11 déc. 2007 à 17:33
Salut!

Je tiens premièrement à te féliciter pour ce code de qualité et pour l'utilisation avancé de la librairie SPL.

Dans mon projet j'utilise les différentes classes que tu partages ici, mais je bute sur un problème :

je n'arrive pas à avoir une liste complète des fichiers uniquement depuis le répertoire source (en clair si mon répertoire source est C:\, je veux tous les fichiers de mon disque dur)

existe-t-il une solution à mon problème ?

je voulais également savoir si ton code était sous une licence spécifique ou il s'agit d'un code totalement libre ?

Merci beaucoup pour tout ce travail c'est vraiment propre

bonne soirée

Cordialement
webdeb Messages postés 488 Date d'inscription samedi 5 avril 2003 Statut Membre Dernière intervention 31 mars 2009 4
7 janv. 2007 à 21:29
Non "au temps pour moi" :)
cs_jean84 Messages postés 449 Date d'inscription jeudi 26 août 2004 Statut Membre Dernière intervention 5 mars 2009
1 déc. 2006 à 17:36
Ah heu.. autant pour moi ^^

@++
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
29 nov. 2006 à 11:10
Ah ben dans ce cas, oui, c'est la même chose, ce sont bien les classes Iterator.
kankrelune Messages postés 1293 Date d'inscription mardi 9 novembre 2004 Statut Membre Dernière intervention 21 mai 2015
29 nov. 2006 à 10:30
Le filtre dont parlent Jean84 sont des filtres qui reposent sur le principe du poka yoké... .. .

@ tchaOo°
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
29 nov. 2006 à 09:15
Pour les filtres, j'ai pigé de quoi tu parlais : l'extension expérimentale PHP5.
ben...non, c'est différent. Ca fonctionne différemment.
Les filtres dont tu parles sont plus des masques destinés à valider ou invalider des données externes arrivant à PHP.
Mais bon, dans le fond, dans les deux cas, ça reste du filtrage oui...mais les 2 n'ont aucun rapport.
cs_jean84 Messages postés 449 Date d'inscription jeudi 26 août 2004 Statut Membre Dernière intervention 5 mars 2009
28 nov. 2006 à 21:34
Wahou ...
laisse moi le temps de digerer tout sa ^^
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
27 nov. 2006 à 18:22
ttp://www.php.net/~helly/php/ext/spl/main.html
ça, C'EST la doc officielle hein...juste une page spécifique pour la SPL, plus complète, bien plus, que celle qu'on trouve ici:
http://fr3.php.net/manual/fr/ref.spl.php

"tu utilises des filtres et j'ai vu que php5 en utilise aussi"
Que veux-tu dire par là...? De quels filtres PHP5 parles-tu?

J'utilise la classe SPL FilterIterator pour implémenter ces filtres.
C'est simplement plus simple pour gférér des filtres appliqués à des itérateurs (en l'occurencence, là, à un DirectoryIterator).

Bon, en détaillant un peu :
La classe smartdir possède deux propriétés de filtres (outre DIR et FILES hein...):
FILTER_ON
FILTER_OFF
La 1ère permet de filtrer, donc, de manière active sur quelquechose. On ne verra que ce qui matche ce filtre.
La 2de fait le contraire : on verra tout SAUF ce qui matche ce filtre.

Je passe par un setter pour les initialiser (__set).

Bien, maintenant, ce qui est important, c'est la classe MyFilter, qui étend RecursiveFilterIterator (elle-même étendant FilterIterator...).
Cette classe se construit avec un itérateur, et pour ma classe, 2 filtres optionnels.
public function __construct ($it, $mFilterOn, $mFilterOff) {
parent::__construct ($it);
$this -> it = $it;
$this -> mFilterOn = $mFilterOn;
$this -> mFilterOff = $mFilterOff;
}

Ici, (et c'est différents pour mes 2 autres package utilisant les itérateurs postés ici), je l'appelle à chaque itération sur mon itérateur courant (le répertoire, quoi).

Les FilterIterator ont plusieurs méthodes, dont 1 qui m'intéresse plus particulièrement:
FilterIterator::accept ().
Je l'ai surchargée, et voici ce que la mienne fait: elle vérifie si quels filtres sont non nuls...déjà ;-)
Puis elle vérifie le type (string, ou tableau de string).
Ensuite, pour la valeur de courante de mon InnerIterator (voir ma classe oUser, gestion utilisateurs, pour plus d'infos à ce sujet...et des filtres plus élaborés), elle vérifie si elle matche le ou la valeur du filtre.
Si oui, et selon le filtre (ON ou OFF), elle retourne un booléen true ou false.

C'est tout...

Le fonctionnement de la SPL se charge du reste : quand je fais mon foreach () ou mon while () sur mon répertoire, si j'ai défini un filtre, ben ce qui doit s'afficher s'affiche.
cs_jean84 Messages postés 449 Date d'inscription jeudi 26 août 2004 Statut Membre Dernière intervention 5 mars 2009
27 nov. 2006 à 18:02
ERRATUM :
Dans "Petit detaille ton systeme de filtre ?" faut comprendre "Peut tu detaille ton systeme de filtre ?"

Desole pour la faute ^^
cs_jean84 Messages postés 449 Date d'inscription jeudi 26 août 2004 Statut Membre Dernière intervention 5 mars 2009
27 nov. 2006 à 18:00
Yep !

Bah en fait j'ai regarder sur la doc officielle (chm telecharger sur php.net en fr) et j'ai trouve la section sur la spl. Je suis tres decu car aucune fonction est documentee (meme pas un bout de code pour presenter la chose... :-( )
Resultat : je part a la chasse aux infos ^^
Par contre petite question : tu utilises des filtres et j'ai vu que php5 en utilise aussi (je travaille sur les classes en ce moment, j'explore toutes les possibilites offertes en poo), y'a-t-il des points commums ? Petit detaille ton systeme de filtre ?

Merci ;-)
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
26 nov. 2006 à 09:35
Hello Jean,

ben non, je suis désolé, je n'ai pas trouvé de doc complète sur la SPL en Français. Je ne pense pas que cela existe encore. Ni même en anglais, à dire vrai...(cet url mis à part : http://www.php.net/~helly/php/ext/spl/main.html mais il reste très complexe à lire).
C'est beaucoup pour ça que j'ai mis ces codes sur CS : monter des exemples concrêts d'utilisation, divers, et complets (pas juste 3 lignes de code simple).
Mais je ne suis pas assez calé pour écrire plus complet, lol, ou pour écrire un vrai tuto.
Faut se contenter des docs et tutos en anglais, pour le moment.
cs_jean84 Messages postés 449 Date d'inscription jeudi 26 août 2004 Statut Membre Dernière intervention 5 mars 2009
24 nov. 2006 à 19:30
Hello !

Sa a l'air sympa ces iterateurs (d'ailleurs merci TheSin pour la difference entre iterateurs et iterations -je savais bien que sa me disait quelque chose..).
Sa ressemble beaucoup au liste chainee du C/C++, j'imagine que c'est la meme chose ?
Derniere question : tu as une doc (en fr please ;-)) qui aprle des iterateurs (fonctionnalite, utilite, mise en oeuvre dans le genre de la doc du DOM par exemple -je sais j'abuse ^^)

Merci et @++
TheSin Messages postés 331 Date d'inscription mardi 12 novembre 2002 Statut Membre Dernière intervention 10 février 2009
23 nov. 2006 à 13:00
ok, merci pour l'exemple, c'est sympa :-)
je regarderais tout ça plus tard, je suis en cours quand même, et malheuresement, le PHP et le C ça se mélange pas :( (pour ceux qui n'ont pas compris, je suis en train de faire du C en cours).

Ton exemple m'a l'air très instructif, encore merci.
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
23 nov. 2006 à 12:37
Bah merci, heureux si ça sert au moins à une personne ;-)
Tien, en primeur, parce que je ne posterai pas vce code avant longtemps je pense, le début d'une vraie classe utilisateur (ce n'est que le début mais ça fait déjà pas mal de choses). C'est long, attention, mais ça te montrera un autre exemple. Elle est faite pour fonctionner à partir de PHP5.0.X (compliqué, en-dessous de PHP 5.1, donc j'ai galéré lol).:
Fichier de classe class.oUser.php

<?php
if (!class_exists ('RecursiveArrayIterator')) { // PHP5 < 5.1
class RecursiveArrayIterator extends ArrayIterator implements RecursiveIterator {

private $ref;

function hasChildren () {
return is_array ($this -> current ());
}

function getChildren () {
if ($this -> current () instanceof self) {
return $this -> current ();
}
if (empty ($this -> ref)) {
$this -> ref = new ReflectionClass ($this);
}
return $this -> ref -> newInstance($this -> current ());
}
}
}

class myFilter extends FilterIterator {

private $oIt = null;
private $mFilter = null;
private $mSubFilter = null;

const ERROR_BAD_FILTERS = 'You cannot have a null FILTER and a not null SUBFILTER';

public function __construct ($oIt, $mFilter null, $mSubFilter null) {
parent::__construct ($oIt);
$this -> oIt = $oIt;
$this -> mFilter = $mFilter;
$this -> mSubFilter = $mSubFilter;
}

public function accept () {
if (!is_null ($this -> mFilter) && is_null ($this -> mSubFilter)) {
if ($this -> oIt -> key () $this -> mFilter && $this -> oIt -> getDepth () 0) {
return true;
}
if ($this -> oIt -> key () $this -> mFilter && $this -> oIt -> getDepth () 1) {
return true;
}
if ($this -> oIt -> getDepth () > 0 && $this -> oIt -> getSubIterator (0) -> key () === $this -> mFilter) {
return true;
}
return false;
}
if (!is_null ($this -> mFilter) && !is_null ($this -> mSubFilter)) {
if ($this -> oIt -> getDepth () > 0 && $this -> oIt -> getSubIterator (0) -> key () === $this -> mFilter) {
if ($this -> key () === $this -> mSubFilter) {
return true;
}
return false;
}
return false;
}
if (is_null ($this -> mFilter) && !is_null ($this -> mSubFilter)) {
throw new Exception (self::ERROR_BAD_FILTERS);
}
return true;
}

}

abstract class abstractUsers extends RecursiveArrayIterator {

protected $aCanBeGet = array (
'FILTER',
'SUBFILTER',
'ITMODE'
);

protected $aCanBeSet = array (
'FILTER',
'SUBFILTER',
'ITMODE'
);

protected $aEachProp = array (
'BDD_NAME' => null,
'VALUE' => null,
'TYPE' => null,
'MANDATORY' => null
);

protected $cItMode = true;
protected $mFilter = null;
protected $mSubFilter = null;
protected $aProps = array ();

protected $oSession = null;
protected $oXml = null;

const ERROR_NOT_SETABLE = '{__PROP__} is not a setable property';
const ERROR_NOT_GETABLE = '{__PROP__} is not a getable property';
const ERROR_PROP_NOT_EXISTS = '{__PROP__} property does not exist';
const ERROR_XML_KEY_NOT_COMPLETE = '{__KEY__} has no children';
const ERROR_XML_FILE_NOT_EXISTS = '{__FILE__} has not been found';
const ERROR_XML_LOADING_FAILED = 'Failed to load {__FILE__}';
const ERROR_PROP_HAS_NO_VALUE = '{__PROP__} property has no value';
const ERROR_CHECKIDENT_BAD_VALUES_COUNT = 'Values given in arguments and Authentication fields do not match';

public function __construct ($fXml) {
if (!file_exists ($fXml)) {
throw new Exception (str_replace ('{__FILE__}', $fXml, self::ERROR_XML_FILE_NOT_EXISTS));
}
if (!($this -> oXml = @simplexml_load_file ($fXml)) instanceof SimpleXMLElement) {
throw new Exception (str_replace ('{__FILE__}', $fXml, self::ERROR_XML_LOADING_FAILED));
}
$this -> oSession = new oSession ($this -> oXml);
$this -> aPropsFill ();
}

private function aPropsFill () {
foreach ($this -> oXml -> USER -> children () as $oNode) {
foreach ($oNode -> children() as $oChild) {
$aTmp[(string)dom_import_simplexml($oChild) -> tagName] = (string)$oChild['value'];
}
if (empty ($aTmp)) {
throw new Exception (str_replace ('{__KEY__}', (string)dom_import_simplexml($oNode) -> tagName, self::ERROR_XML_KEY_NOT_COMPLETE));
}
$this -> aProps[(string)dom_import_simplexml($oNode) -> tagName] = $aTmp;
}
}

public function __get ($sProp) {
if (!in_array ($sProp, $this -> aCanBeGet) && !array_key_exists ($sProp, $this -> aProps)) {
throw new Exception (str_replace ('{__PROP__}', $sProp, self::ERROR_NOT_GETABLE));
}
switch ($sProp) {
case 'FILTER' :
return $this -> mFilter;
break;
case 'SUBFILTER' :
return $this -> mSubFilter;
break;
case 'ITMODE' :
return $this -> cItMode;
break;
default :
if (!isset ($this -> aProps[$sProp])) {
throw new Exception (str_replace ('{__PROP__}', $sProp, self::ERROR_PROP_NOT_EXISTS));
}
if (!isset ($this -> aProps[$sProp]['VALUE'])) {
throw new Exception (str_replace ('{__PROP__}', $sProp, self::ERROR_PROP_HAS_NO_VALUE));
}
return $this -> aProps[$sProp]['VALUE'];
break;
}
}

public function __set ($sProp, $mVal) {
if (!array_key_exists ($sProp, $this -> aProps) && !in_array ($sProp, $this -> aCanBeSet)) {
throw new Exception (str_replace ('{__PROP__}', $sProp, self::ERROR_NOT_SETABLE));
}
switch ($sProp) {
case 'FILTER' :
$this -> mFilter = $mVal;
break;
case 'SUBFILTER' :
$this -> mSubFilter = $mVal;
break;
case 'ITMODE' :
$this -> cItMode = $mVal;
break;
default :
$this -> aProps[$sProp]['VALUE'] = $mVal;
break;
}
}

public function getProps () {
if (!is_null ($this -> mFilter)) {
if (is_string ($this -> mFilter)) {
return new myFilter (new RecursiveIteratorIterator (new RecursiveArrayIterator ($this -> aProps), $this -> cItMode), $this -> mFilter, $this -> mSubFilter);
}
}
return new RecursiveIteratorIterator (new RecursiveArrayIterator ($this -> aProps), $this -> cItMode);
}

abstract public function checkIdent ($sTable, $aValues);

}

class oSession {

private $aProps = array ();
private $oXml;

public function __construct ($oXml) {
$sSessionId = session_id ();
if (empty ($sSessionId)) {
session_start ();
}
$this -> oXml = $oXml;
}

private function aPropsFill () {
foreach ($this -> oXml -> SESSION -> children () as $oNode) {
foreach ($oNode as $oChild) {
$this -> aProps[(string)dom_import_simplexml($oChild) -> tagName] = null;
}
}
print_r ($this -> aProps);
}

public function __get ($sProp) {

}

public function __set ($sProp, $mVal) {

}
}

class oUser extends abstractUsers {

private $oDB;

public function __construct ($sXml, oDB $oDB) {
parent::__construct ($sXml);
$this -> oDB = $oDB;
}

public function checkIdent ($sTable, $aValues) {
$sTmp = $this -> mFilter;
$this -> mFilter = 'IDENT';
$aProps = $this -> getProps ();
foreach ($aProps as $sV) {
$sCurrentDbName = $this -> aProps [$aProps -> getInnerIterator () -> getSubIterator (0) -> key ()]['BDD_NAME'];
if (empty ($aValues[$sCurrentDbName])) {
throw new Exception (self::ERROR_CHECKIDENT_BAD_VALUES_COUNT);
}
$aIdent[] = $sCurrentDbName.' = \''.$aValues[$sCurrentDbName].'\'';
}
$this -> mFilter = $sTmp;
if (count ($aValues) !== count ($aIdent)) {
throw new Exception (self::ERROR_CHECKIDENT_BAD_VALUES_COUNT);
}
$sWhereClause = implode (' AND ', $aIdent);
$sQuery = 'SELECT '.$this -> aProps['ID']['BDD_NAME'].' FROM '.$sTable.' WHERE '.$sWhereClause;
$this -> oDB -> query ($sQuery);
$aRes = $this -> oDB -> fetch_assoc ();
if (!empty ($aRes[$this -> aProps['ID']['BDD_NAME']])) {
echo 'OK';
return true;
} else {
echo 'KO';
return false;
}
}
}
?>

Fichier test.php
<?php
DEFINE ('SQL_LOGIN', 'xxx');
DEFINE ('SQL_PWD', 'xxx');
DEFINE ('SQL_DB', 'xxx');
DEFINE ('SQL_HOST', 'xxx');

require_once 'class.oDB.php';
require_once 'class.oUser.php';

$oDB = new oDB(SQL_HOST, SQL_LOGIN, SQL_PWD, SQL_DB);

$fXml = 'config.xml';
try {
$oUser = new oUser ($fXml, $oDB);
} catch (Exception $e) {
echo $e -> getMessage ();
}

try {
echo '
ALL NO VALUE
';
$aProps = $oUser -> getProps ();
foreach ($aProps as $sK = > $sV) {
echo str_repeat ('---', $aProps -> getDepth ()), $sK, ' => ', $sV, '
';
}

$oUser -> EMAIL = 'test@test.com';
$oUser -> PASSWORD = 'mypass';
$oUser -> ID = 666;

echo '
EMAIL VALUE
';
echo $oUser -> EMAIL, '
';

echo '
ALL with VALUES
';
$aProps = $oUser -> getProps ();
foreach ($aProps as $sK = > $sV) {
echo str_repeat ('---', $aProps -> getDepth ()), $sK, ' => ', $sV, '
';
}

echo '
ONLY VALUES
';
$oUser -> FILTER = 'VALUE';
$aProps = $oUser -> getProps ();
foreach ($aProps as $sK => $sV) {
echo $sK, ' => ', $sV, '
';
}

echo '
ONLY BDD_NAMES
';
$oUser -> FILTER = 'BDD_NAME';
$aProps = $oUser -> getProps ();
foreach ($aProps as $sK => $sV) {
echo $sK, ' => ', $sV, '
';
}

echo '
ONLY EMAIL
';
$oUser -> FILTER = 'EMAIL';
$aProps = $oUser -> getProps ();
foreach ($aProps as $sK => $sV) {
echo str_repeat ('---', $aProps -> getInnerIterator () -> getDepth ()), $sK, ' => ', $sV, '
';
}

echo '
ONLY EMAIL BDD_NAME
';
$oUser -> FILTER = 'EMAIL';
$oUser -> SUBFILTER = 'BDD_NAME';
$aProps = $oUser -> getProps ();
foreach ($aProps as $sK => $sV) {
echo $sK, ' => ', $sV, '
';
}

$oUser -> FILTER = null;
$oUser -> SUBFILTER = null;
echo '
BACK TO ALL NO FILTER
';
$aProps = $oUser -> getProps ();
foreach ($aProps as $sK = > $sV) {
echo str_repeat ('---', $aProps -> getDepth ()), $sK, ' => ', $sV, '
';
}

} catch (Exception $e) {
echo $e -> getMessage ();
}

try {
echo '
CHECK IDENT (WRONG ONE)
';
$oUser -> checkIdent ('users', array ('user_pwd' => 'pwd', 'user_email' = > 'moi@moi.com'));

echo '
CHECK IDENT (GOOD ONE)
';
$oUser -> checkIdent ('users', array ('user_pwd' => 'toto', 'user_email' => 'toto@bled.com'));
} catch (Exception $e) {
echo $e -> getMessage ();
}


$oDB -> close ();
?>

et le fichier de config xml :
<?xml version="1.0" encoding="iso-8859-1"?>
Configuration: 



<TYPE value="int" />
<MANDATORY value="true" />



<TYPE value="string" />
<MANDATORY value="true" />




<TYPE value="string" />
<MANDATORY value="true" />




<SESSION>


</SESSION>


Pour le reste, tu te débrouilles ;-)
TheSin Messages postés 331 Date d'inscription mardi 12 novembre 2002 Statut Membre Dernière intervention 10 février 2009
23 nov. 2006 à 12:20
aaaa, merci Malalam, c'était complet et direct :-)
J'ai donc compris la subtile différence de vocabulaire ;-)
Je crois qu'on peut pas faire mieux comme tutorial :)
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
23 nov. 2006 à 12:07
Tu remarqueras que je fais des foreach ()...
Bon en gros, le principe de base : dès qu'on implémente une classe ou une interface itérateur (Iterator en anglais), le foreach appelle implicitement les méthodes itérateurs.
Avec un while, on appelle manuellement les méthodes.
On peut aussi très simplement implémenter dans une classe l'interface iteratorAggregate, et surcharger ou non les méthodes.
Bref, faut bien lire les différents tutos.

regarde ce code :
<?php

$dir = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator('.'), true);

foreach ( $dir as $file ) {
echo str_repeat('-', $dir->getDepth()) . ' '.$file.'
';
}
?>
On instancie la classe RecursiveIteratorIterator, qui définit un itérateur récursif (valid, next, key, current, hasChild, getChild, en gros). Il a besoin d'un itérateur dédié : on lui donne donc un itérateur RecursiveDirectoryIterator qui prend un chemin comme argument, et permet de récupérer l'arborescence complète.
Puis on fait un foreach sur l'itérateur récupéré ($dir), qui permet d'afficher toute l'arborescence du répertoire. La méthode getDepth () est simplement là pour indenter l'arborescence.
Le foreach () appelle automatiquement les méthodes nécessaires : rewind () au début, puis valid ?, current (key éventuellement), next...jusqu'à ce que valid renvoie false.

Point barre.

Bref, on peut faire très simple...ou plus compliqué quand on veut faire des choses bien spécifiques (comme moi dans ces codes).

Un autre exemple simple :
http://fr3.php.net/manual/fr/language.oop5.iterations.php
pour parcourir un objet comme on le désire.
Soit en surchargeant Iterator, soit en implémentant l'interface IteratorAggregate.
TheSin Messages postés 331 Date d'inscription mardi 12 novembre 2002 Statut Membre Dernière intervention 10 février 2009
23 nov. 2006 à 11:23
oui, en fait c'est justement ça.
en cours, on apprend qu'une itération c'est une boucle, qu'elle compte ou non (même un "while(;;)").
ici, si je comprend bien, ce que tu appelle itérateur, c'est le fait qu'on ai une itération implicite via les next ?
Justement, j'aimerais appronfondir les itérateurs, que ça soit en php ou autre ;-)
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
23 nov. 2006 à 08:08
Pas itération dans le sens "compteur", en tous cas. Mais en français, une itération, c'est une répétition. Et dans ce cadre, un itérateur fait bien des répétitions : current, next, current, next, current, next... ;-)
Bref...peux tu être plus précis dans ta question ? :-) Que veux tu savoir exactement ? je tâcherai de répondre de mon mieux (je ne suis pas un pro des "itérateurs" en php...j'y travaille, lol, mais bon...)
TheSin Messages postés 331 Date d'inscription mardi 12 novembre 2002 Statut Membre Dernière intervention 10 février 2009
23 nov. 2006 à 07:28
malalam, si je comprend bien ton explication, il ne faut pas confondre itérateur et itération ?
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
21 nov. 2006 à 04:37
'tite insomnie... ;-)
Un itérateur, c'est...heu...une méthode permettant d'accéder aux éléments d'une collection l'un après l'autre. Un itérateur n'utilise de ressource que pour l'élément en cours. Bref pour parcourir 1,2,3, ben via un itérateur, tu vas faire un rewind pour être au début, puis un next et tu ne connaitras toujours que l'élément en cours (1, puis 2, puis 3). Tu traverses la collection (traversablité est un maître mot pour les itérateurs), récursivement si tu utilises un itérateur récursif, sans utiliser d'autre ressource que celle utilisée pour connaître l'élément en cours.
Tu déclares ton itérateur sur un répertoire par exemple, en récursif, et il te suffit d'un foreach () sur ton itérateur pour lire TOUTE l'arborescence. Parce que le foreach () va aller chercher les méthodes de l'itérateur permettant de le traverser : rewind (), next (), valid (), key (), current (), et si récursivité, hasChild (), getChild (). Ca, c'est l'exemple basique hein...pour les interfaces Iterator et RecursiveIterator. Mais il y a des itérateurs implémentant ces interfaces qui permettent bien plus.
La SPL définit des itérateurs pour un peu tout, et surtout, des méthodes et interfaces très complètes pour chacun de ces itérateurs.
Je donnerai d'autres exemples, notamment le très sympa IteratorAggregate.
Ici, par exemple, le coup du "un par un" m'a pas mal embêté pour la méthode oSmartDir::copy () :
je crée mon itérateur sur le répertoire courant pour le copier dans mon nouveau répertoire, puis je crée le répertoire destination. Oui mais comme je copie en traversant mon itérateur...je finis par tomber sur le répertoire que j'ai créé, et dans lequel j'ai copié les éléments précédents! Donc, je fais next (), hasChild () => true ? getChild () ...etc et je copie...récursivement, et dans une boucle infinie. Puisqu'au fur et à mesure que je copie, ben je parcours... ;-)
C'est pourquoi j'ai dû ajouter un filtre privé sortant de la méthode oSmartDir::valid() en false si j'étais sur le répertoire destination. Histoire de ne pas rentrer dedans et le traverser.
cs_jean84 Messages postés 449 Date d'inscription jeudi 26 août 2004 Statut Membre Dernière intervention 5 mars 2009
20 nov. 2006 à 18:53
Salut !

Concretement, c'est quoi un iterateur ? J'en avais entendu parler en ce qui concerne les if() else() for & autres mais la j'ai du mal ;-)

Merci !
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
20 nov. 2006 à 13:37
C'est très, très puissant...mais très, très complexe lol. Très!
J'ai oublié de mettre un lien bien pratique :
http://www.php.net/~helly/php/ext/spl/main.html

Il montre toutes les implémentations des nombreuses classes de la SPL (bien plus que l'on peut en trouver sur la doc "normale", quelques exemples, et des liens très intéressants vers divers tuto.

Cet exemple n'est certainement pas optimisé, et ne tire certainement pas partie de toute la puissance des itérateurs. Mais bon, j'y travaille, je trouve ça intéressant et du coup, je veux faire partager mes découvertes :-)
kankrelune Messages postés 1293 Date d'inscription mardi 9 novembre 2004 Statut Membre Dernière intervention 21 mai 2015
20 nov. 2006 à 13:05
Ca à l'air pô mal du tout tout ça... faudra que je teste... .. .

Je connais pas trop les iterator de php5... faut dire que je suis à la traine en ce qui concerne php5... .. . :oS

@ tchaOo°
Rejoignez-nous