Bonjour à tous.

Je vous propose la classe PDOStatementIterator. J'ai été amené à créer cette classe pour faciliter l'usage des Iterators avec les PDOStatement car bien que ces derniers implémentent l'interface Traversable, il n'est pas possible de l'utiliser comme un Iterator (du moins pas directement). Il est vrai que l'usage de IteratorIterator nous permet de contourner ce problème, mais on aimerai grandement pouvoir se positionner dans le PDOStatement (SeekableIterator) et compter le nombre de lignes retournées (Countable), c'est là que PDOStatement entre en scène.

Voici le code source de la classe:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 
class PDOStatementIterator extends IteratorIterator implements SeekableIterator, Countable {
 
    protected $_statement;
 
    protected $_count;
 
    public function __construct (PDOStatement $statement) {
        parent::__construct($this->_statement = $statement);
    }
 
    public function seek ($position) {
        if ($position > $this->count() || $position < $this->key())
            throw new OutOfBoundsException("Cannot seek to $position");
 
        for ($i = $this->key(); $i < $position; $i++)
            $this->next();
    }
 
    public function count () {
        if (!isset($this->_count))
		    return $this->_count = $this->_statement->rowCount();
	    return $this->_count;
    }
}
Cette classe est ni plus ni moins qu'un IteratorIterator seekable et coutable... On conserve une référence sur le PDOStatement à cet effet.
L'usage de cette classe est indépendant du fetch_mode choisi dans le PDOStatement, ce qui la rends bien pratique pour récupérer des collections en LazyLoading.
Exemple:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 
class User { 
  protected $_data;
 
  public function __get ($key) {
    return isset($this->_data[$key]) ? $this->_data[$key] : null;
  }
 
  public function __set ($key, $value) {
	$this->_data[$key] = $value;
  }
}
 
// ...
 
$user = new User;
 
$stmt = $pdo->prepare('SELECT * FROM `users`');
$stmt->setFetchMode(PDO::FETCH_INTO, $user);
$stmt->execute();
 
$it = new PDOStatementIterator($stmt);
$itit = new LimitIterator($it, 10, 20);
foreach ($itit as $user) {
  var_dump($user);
}
Une amélioration possible serait d'étendre NoRewindIterator au lieu de IteratorIterator, mais je n'ai pas encore réussi à la faire marcher dans ce sens...

Voir également la discussion d'origine: http://www.developpez.net/forums/d10...oo-orm-entite/

Vos commentaires sont les bienvenus.