Précédent   Forum des professionnels en informatique > PHP > Langage

Langage Forum sur le langage PHP, la POO, les conventions, la sécurité, etc. Avant de poster : FAQ Langage, toutes les FAQ PHP, cours langage et sources PHP

Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Affichage des résultats du sondage: Que retournez-vous ?
tableau 0 0%
collection 4 100,00%
recordset 0 0%
Votants: 4. Vous ne pouvez pas participer à ce sondage.

Publicité
'
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Vieux 23/03/2011, 23h11   #1
Membre régulier
 
Inscription : avril 2003
Messages : 325
Détails du profil
Informations forums :
Inscription : avril 2003
Messages : 325
Points : 80
Points : 80
Par défaut POO ORM Entité

Bonjour,

Prenons un exemple : vous souhaitez retourner la liste des utilisateurs.

Vous créez une méthode (static par exemple), dans une classe "User".

Que retourner vous ?
- un tableau,
- une collection (d'objets),
- le recordset directement issu de la requête.

La collection semble vraiment être la solution la plus propre et maintenable, mais aussi la plus lourde.

Pourquoi parcourir le recordset pour créer un tableau manuellement à retourner alors que le code qui va appeler la méthode va re-parcourir ce même tableau (donc 2 parcours) ?

Comment vous y prenez-vous ? Pourquoi ?

Merci
dorian53 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/03/2011, 09h53   #2
Membre Expert
 
Avatar de transgohan
 
Homme Baptiste ROUSSEL
Étudiant
Inscription : janvier 2011
Messages : 802
Détails du profil
Informations personnelles :
Nom : Homme Baptiste ROUSSEL
Localisation : France, Territoire de Belfort (Franche Comté)

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : janvier 2011
Messages : 802
Points : 1 515
Points : 1 515
Pour ma part je stocke une collection d'objet et je libère la ressource SQL.

Pourquoi pas un tableau ? Parce que je trouve plus propre et plus personnalisable d'utiliser des objets.

Pourquoi pas le recordset ? Parce que garder indéfiniment des tonnes de recordset en mémoire n'est pas franchement optimisé.
transgohan est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/03/2011, 10h55   #3
Modérateur
 
Avatar de Benjamin Delespierre
 
Benjamin Delespierre
Développeur Web
Inscription : février 2010
Messages : 2 984
Détails du profil
Informations personnelles :
Nom : Benjamin Delespierre
Âge : 24
Localisation : France

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : février 2010
Messages : 2 984
Points : 5 014
Points : 5 014
Je récupère dans une collection qui fonctionne en lazy loading.

J'utilise ensuite un Iterator qui me permet de créer les objets sur demande, cela évite la charge inutile. De plus le fait d'utiliser un Iterator permet l'usage du LimitIterator qui est bien pratique pour la pagination.
__________________
A la recherche d'un framework MVC facile a prendre en main ? Essayez Axiom
Nouveau: la référence d'Axiom est disponible sur GitHub (je la peaufine en ce moment même).

Un problème correctement identifié est à moitié résolu, évitez de poster l'intégralité de votre code avec pour seule explication "ça ne marche pas...".
Pour identifier correctement vos problèmes PHP, utilisez la gestion des erreurs et xdebug.

Les boutons et existent, servez-vous en
Benjamin Delespierre est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/03/2011, 10h02   #4
Membre régulier
 
Inscription : avril 2003
Messages : 325
Détails du profil
Informations forums :
Inscription : avril 2003
Messages : 325
Points : 80
Points : 80
Le problème du lazyload dans un parcours c'est qu'il va exécuter N requêtes pour récupérer l'objet.

OK pour l'objet y'a pas photo, mais les "new" sont très gourmands alors que l'on possède déjà toutes les données "à plat" dans le recordset ?
dorian53 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/03/2011, 10h59   #5
Membre Expert
 
Avatar de transgohan
 
Homme Baptiste ROUSSEL
Étudiant
Inscription : janvier 2011
Messages : 802
Détails du profil
Informations personnelles :
Nom : Homme Baptiste ROUSSEL
Localisation : France, Territoire de Belfort (Franche Comté)

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : janvier 2011
Messages : 802
Points : 1 515
Points : 1 515
Mais en cas de grosse requête le recordset est très lourd aussi, de plus cela peut gêner les prochaines requêtes si tu ne le libères pas.
transgohan est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/03/2011, 11h17   #6
Modérateur
 
Avatar de Benjamin Delespierre
 
Benjamin Delespierre
Développeur Web
Inscription : février 2010
Messages : 2 984
Détails du profil
Informations personnelles :
Nom : Benjamin Delespierre
Âge : 24
Localisation : France

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : février 2010
Messages : 2 984
Points : 5 014
Points : 5 014
Citation:
Le problème du lazyload dans un parcours c'est qu'il va exécuter N requêtes pour récupérer l'objet.
En effet, mais cette solution est plus pratique que performante. Ceux qui veulent une performance accrue peuvent utiliser PDO::FETCH_INTO ou PDO::FETCH_CLASS. Le problème est que bien que le PDOStatement soit traversable il n'implémente pas Iterator et donc, pas de LimitIterator (ou autres FilterIterator). On devrait cependant pouvoir faire un PDOStatementIterator sans trop se casser la tête, c'est à creuser...

Citation:
OK pour l'objet y'a pas photo, mais les "new" sont très gourmands alors que l'on possède déjà toutes les données "à plat" dans le recordset ?
Je fais ça en deux passes (je sais pertinemment que ce n'est pas optimal):
- une query réccupère les id et les passe à un RecordsetIterator en lui fournissant le nom de la classe à invoquer pour le fech.
- la méthode current du RecordsetIterator génère les objets pour l'id courant.
L'idée n'est bien sûr pas d'appliquer ce traitement sur de larges ensembles d'objets mais sur des sous-ensemble des 10 ou 20 éléments.

Citation:
Mais en cas de grosse requête le recordset est très lourd aussi, de plus cela peut gêner les prochaines requêtes si tu ne le libères pas.
Cela dépends de ton driver.

Voici à quoi ressemble le recordset (réduit à sa plus simple expression):
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
class RecordsetIterator extends ArrayIterator {
 
    protected $_class;
 
    public function __construct ($array, $class) {
        if (!$class || !class_exists($class, true))
            throw new RuntimeException("Unknown class $class");
 
        parent::__construct($array);
        $this->_class = $class;
    }
 
    public function current () {
        return new $this->_class (parent::current());
    }
}
Voici comment il est utilisé par une méthode d'un modèle:
Code :
1
2
3
4
5
6
7
8
9
10
 
    public static function getArticles () {
        $query = "SELECT `id` FROM `blog`.`articles`";
 
        if ($stmt = Database::query($query)) {
            $results = $stmt->fetchAll(PDO::FETCH_COLUMN, 0);
            return new RecordsetIterator(array_map('implode', $results), __CLASS__);
        }
        return false;
    }
-- Edit
Si j'ai le temps je fournirai un prototype pour le PDOStatementIterator évoqué plus haut.
__________________
A la recherche d'un framework MVC facile a prendre en main ? Essayez Axiom
Nouveau: la référence d'Axiom est disponible sur GitHub (je la peaufine en ce moment même).

Un problème correctement identifié est à moitié résolu, évitez de poster l'intégralité de votre code avec pour seule explication "ça ne marche pas...".
Pour identifier correctement vos problèmes PHP, utilisez la gestion des erreurs et xdebug.

Les boutons et existent, servez-vous en
Benjamin Delespierre est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/03/2011, 15h14   #7
Modérateur
 
Avatar de Benjamin Delespierre
 
Benjamin Delespierre
Développeur Web
Inscription : février 2010
Messages : 2 984
Détails du profil
Informations personnelles :
Nom : Benjamin Delespierre
Âge : 24
Localisation : France

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : février 2010
Messages : 2 984
Points : 5 014
Points : 5 014
Voici à quoi pourrait bien ressembler notre StatementIterator.
Pour l'utiliser comme un factory d'objet, il est nécéssaire de définir le fetch-mode de PDOStatement avant d'instancier cette classe.

Code :
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
 
<?php
 
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())
            throw new OutOfBoundsException("Cannot seek to $position");
 
        if ($position < $this->key())
            throw new OutOfRangeException("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;
    }
}
 
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;
  }
}
Il s'utilise ainsi:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 
echo "<pre>";
 
$db = "backoffice";
$db_type = "mysql";
$db_user = "root";
$db_password = "";
$db_host = "localhost";
$pdo = new PDO("$db_type:dbname=$db;host=$db_host", $db_user, $db_password);
 
$user = new User;
 
$stmt = $pdo->prepare('SELECT * FROM `backoffice`.`users`');
$stmt->setFetchMode(PDO::FETCH_INTO, $user);
$stmt->execute();
 
$it = new PDOStatementIterator($stmt);
 
var_dump(count($it));
foreach ($it as $user) { var_dump($user); }
 
echo "</pre>";
Vos commentaires sont les bienvenus.
__________________
A la recherche d'un framework MVC facile a prendre en main ? Essayez Axiom
Nouveau: la référence d'Axiom est disponible sur GitHub (je la peaufine en ce moment même).

Un problème correctement identifié est à moitié résolu, évitez de poster l'intégralité de votre code avec pour seule explication "ça ne marche pas...".
Pour identifier correctement vos problèmes PHP, utilisez la gestion des erreurs et xdebug.

Les boutons et existent, servez-vous en
Benjamin Delespierre est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 21h49.


 
 
 
 
Partenaires

Hébergement Web