Lecture/écriture avec PDO d'objets dont les attributs sont des objets

Eléphanteau du PHP | 10 Messages

24 août 2008, 14:03

Bonjour à tous,

Au sein d'une application web à but pédagogique en PHP5, j'utilise des objets dont les valeurs des attributs sont elles-même des objets ou des tableaux dont les valeurs sont des objets. Quelque chose du genre suivant :
<?php
class variable{
    public $description;
    public $nom;
    public $type;
    public function verifie_type(){
        // instructions de vérification
    }
}
class fonction{
    public $auteur;
    public $description;
    public $code;
    public $variables = array();
    public function execute_toi(){
        // Instructions d'exécution
    }
    // ...
}
$a = new variable;
$a->description = " est un nombre compris entre 2 et 12.";
$a->nom = "\$a";
$a->type = "integer";
$b = new variable;
$b->description = " est le nom d'une inconnue mathématique ('x', 'y'...)";
$b->nom = "\$b";
$b->type = "string";

$f = new fonction;
$f->auteur = "Philippe";
$f->description = "Demande le double ou le carré d'un monome.";
$f->code = "    \$cd = (mt_rand(0,1) == 0) ? 'carré' : 'double';
    return \"Que vaut le \$cd de \$a\$b ?\";";
$f->variables = array($a,$b);
?>
De fait, dans mon application, il y a quatre niveaux "d'objet dont les attributs sont des objets dont etc."

Je cherche à stoker des instances de la classe fonction dans une base de données mySQL. J'utilise PDO avec la méthode PDO::fetchObject(). Mais je n'ai pas trouvé avec la documentation en-ligne et celle dont je dispose de méthode efficace pour écrire et recharger un tel objet.

Quelqu'un aurait-il une piste à me suggérer ? Ou bien est-ce la structuration des données qui est à revoir ?

Cordialement.
jmb

Eléphant du PHP | 259 Messages

25 août 2008, 15:20

slt

si je comprends bien tu veux sérialiser puis stocker dans une bdd ?

++
l'hébergeur gratuit que j'utilisais: http://www.freeheberg.com (pas de limitte de débit, BP, 1à10Go, bdd mysql illimitées )
mainteant je suis chez OVH, payant mais plus adapté à de gros sites

Eléphanteau du PHP | 10 Messages

25 août 2008, 15:53

Bonjour,

En fait, je viens de découvrir que la méthode PDO::fetchObject() recréé l'instanciation automatique de nos objets lorsqu'on lui fournit la déclaration de classe et les valeurs des attributs dans des champs portant le même nom alors que je m'apprétais à rédiger de trop nombreuses lignes qui sérialisent, enregistrent, désérialisent et instancient. De plus cette technique offre la possibilité de lancer des requêtes SQL portant sur le contenu des champs, c'est-à-dire, les valeurs des attributs des objets une fois qu'il seront rechargés.

Bref, du travail en moins et de la souplesse dans le stockage. Mais du fait que les valeurs de mes attributs sont elles-mêmes des objets, celles-ci ne peuvent s'instancier automatiquement lors de l'utilisation de PDO::fetchObject(). Et j'ai la triste impression que je vais devoir quand même faire ce travail. Or, justement, non : je voudrais ne pas sérialiser.

Est-ce possible ? Existe-il une fonction PHP et une structure correspondante de base de données qui, à l'instar de PDO::fetchObject(), réinstancie automatiquement les objets en affectant à chaque attribut la valeur du champ de la BD portant le même nom mais qui, dans le cas où des "sous-valeurs" seraient des objets, les réinstancierait, et ce, récursivement ?

Cordialement,
J.-M. B.
Modifié en dernier par calculatio le 26 août 2008, 00:42, modifié 1 fois.

ViPHP
ViPHP | 5924 Messages

25 août 2008, 18:36

As tu essayé d'étendre la classe PDO pour modifier le comportement de cette méthode sans la réimplémenter complètement ?

Eléphanteau du PHP | 10 Messages

27 août 2008, 03:15

Bonsoir,

J'ai maintenant compris que c'est la structure de base de données qui est en cause dans mon problème grâce aux notions (sûrement très élémentaires) de modèle conceptuel de données et de modèle physique de données.

Comme tu me l'as suggéré Sékiltoyai, j'ai donc essayé d'étendre la classe PDOStatement::fetchObject(). Pour cela je me suis placé dans un cas simple où une classe grande_classe contient dans son attribut $petits_objets un array d'objets de classe petite_classe. J'ai organisé mes tables ainsi :
  • les objets de classe grande_classe sont enregistrés dans la table `g`(reference, attribut1, attribut2) et
  • ceux de classe petite_classe dans dans la table `p`(id, a, b, reference)
J'ai créé la fonction multiFetchObject() qui fait ce que j'espèrais, à savoir instancier un $grand_objet dont l'attribut petis_objets contient un array d'instances de petite_classe :
<?php
class grande_classe{
    public $petits_objets;
    public $attribut1;
    public $attribut2;
}
class petite_classe{
    public $a;
    public $b;
}
function multiFetchObject($stmt,$dbh){
    $grande          = $stmt->fetch(PDO::FETCH_ASSOC);
    $req_sql_petite  = "SELECT  `a` , `b` FROM `p` "
                     . "WHERE ( `reference` = '{$grande['reference']}' ) ;";
    $stmt_petite     = $dbh->query($req_sql_petite);
    $petits_objets   = array();
    for ($i=1;$i<=$stmt_petite->rowcount();$i++){
        $petit_objet     = $stmt_petite->fetchObject('petite_classe');
        $petits_objets[] = $petit_objet;
    };
    $grand_objet                = new grande_classe;
    $grand_objet->petits_objets = $petits_objets;
    $grand_objet->attribut1     = $grande['attribut1'];
    $grand_objet->attribut2     = $grande['attribut2'];
    return $grand_objet;
}
$dbh = new PDO($dsn, $user,$pass);
$req_sql_grande = 'SELECT * FROM `g` LIMIT 0, 30 ';
$stmt           = $dbh->query($req_sql_grande);
$grand_objet    = multiFetchObject($stmt,$dbh);
print_r($grand_objet);
?>
Je n'ai pas su déclarer cette fonction comme méthode d'une extenstion de PDO ou PDOStatement... De plus, j'ai vu qu'il y avait en mySQL des foreign keys que je n'ai pas encore réussi à utiliser est-ce fait pour lier des tables ? Comment les utilises-t-on ?

Cordialement,
J.-M. B.

ViPHP
ViPHP | 5924 Messages

27 août 2008, 09:00

Euh, tu sais ce que signifie l'héritage ?
Tu n'as pas l'air : http://www.php.net/manual/fr/language.o ... ic.extends

Eléphant du PHP | 443 Messages

27 août 2008, 12:01

[...]
Bref, du travail en moins et de la souplesse dans le stockage. Mais du fait que les valeurs de mes attributs sont elles-mêmes des objets, celles-ci ne peuvent s'instancier automatiquement lors de l'utilisation de PDO::fetchObject(). Et j'ai la triste impression que je vais devoir quand même faire ce travail. Or, justement, non : je voudrais ne pas sérialiser.
[...]

Tu vas dans le mur, bien sur que certaines propriétés de tes objets font référence à d'autres objets, l'information est relationnelle. Ce qui est improbable c'est imaginer constituer un système où dès lors que tu montes un objets en mémoire, tous ceux vers lesquel il pointe le soient également, en un seul ordre tu vas probablement remonter la base entière ou pas loin.

Alors laisse les object_id à l'intérieur de ton objet, et en t'appuyant sur une description des relations dans ta base et sur les méthodes __get/__set, récupère les objets dépendants seulement quand c'est nécessaire.

Un autre problème se superpose à ce principe, c'est le lockage des objets, à toi de voir si tu souhaites gérer l'affaire pour garantir correctement l'exclusivité.


Tracker.

Eléphanteau du PHP | 10 Messages

28 août 2008, 19:36

Bonjour,

Merci pour vos réponses.

Sékiltoyai, je crois avoir une idée de ce qu'est l'héritage pour avoir potassé sérieusement le livre PHP 5 avancé (Eyrolles) mais j'ai très peu d'expérience ! J'avais d'abord implémenté cette fonction comme méthode de multiPDOStatement qui étendait PDOStatement et redéfinissait PDOStatement::fetchObjet(). Mon actuel paramètre d'entrée $stmt était donc $this dans ce contexte.

Mais mon problème, surement trivial ! est le suivant : d'une part je ne sais pas convertir mon objet $stmt de classe PDOStatement fourni par PDO::query() en multiPDOStatement et d'autre part j'ai le présentiment que le fait de passer $dbh en paramètre n'est pas un bonne méthode.

J'ai beaucoup de choses à apprendre sur les bases de données, entre autres... Je ne suis qu'un "embryon" :lol: Je m'y colle en ce moment.

Tracker, merci pour tes conseils. Je vais me documenter sur ces histoires de "relations", de "lockage" et d'"exclusivité" que je ne connais pas.

Cordialement,
J.-M. B.