Tableau 6.2 — Les méthodes d’interaction avec la base de la classe TableBD.. Conversion des données de la base vers une instance de TableBD La classe ou plus exatement les objets instanc
Trang 1Nous allons reprendre la classe générique IhmBD déjà présentée partiellement dans le chapitre 3, consacré à la programmation objet (voir page 167) et l’étendre dans l’optique d’un Modèle MVC aux aspects propres à la recherche et à la mise à jour de la base Elle s’appellera maintenant TableBD Le tableau 6.2 donne la liste des méthodes génériques assurant ces fonctions (ce tableau est complémentaire de celui déjà donné page 170)
Tableau 6.2 — Les méthodes d’interaction avec la base de la classe TableBD
.
chercherParCle (cl´ e) Recherche d’une ligne par clé primaire.
insertion (donn´ ees) Insertion d’une ligne.
Conversion des données de la base vers une instance de TableBD
La classe (ou plus exatement les objets instance de la classe) vont nous servir à interagir avec une table particulière de la base de données Le but est de pouvoir manipuler les données grâce aux méthodes de la classe, en recherche comme en insertion La première étape consiste à récupérer le schéma de la table pour connaître
la liste des attributs et leurs propriétés (type, ou contraintes de clés et autres) Il faut aussi être en mesure de stocker une ligne de la table, avant une insertion ou après une recherche Pour cela nous utilisons deux tableaux, pour le schéma, et pour les données
p r o t e c t e d $schema = a r r a y ( ) ; / / Le s c h é m a d e l a t a b l e
p r o t e c t e d $ d o n n e e s = a r r a y ( ) ; / / L e s d o n n é e s d ’ u n e l i g n e
La déclaration protected assure que ces tableaux ne sont pas accessibles par une application interagissant avec une instance de la classe En revanche ils peuvent être modifiés ou redéfinis par des instances d’une sous-classe de TableBD Comme nous le verrons, TableBD fournit des méthodes génériques qui peuvent être spécialisées par des sous-classes
Pour obtenir le schéma d’une table nous avons deux solutions : soit l’indiquer explicitement, en PHP, pour chaque table, soit le récupérer automatiquement en interrogeant le serveur de données Notre classe BD dispose déjà d’une méthode, schemaTable(), qui récupère le schéma d’une table sous forme de tableau (voir page 132) Nous allons l’utiliser Cette méthode prend en entrée un nom de table et retourne un tableau comportant une entrée par attribut Voici par exemple ce que
l’on obtient pour la table Internaute.
A r r a y
(
[ e m a i l ] => A r r a y (
[ l o n g u e u r ] => 40 [ t y p e ] => s t r i n g [ c l e P r i m a i r e ] => 1 [
n o t N u l l ] => 1 )
Trang 2[ nom ] => A r r a y (
[ l o n g u e u r ] => 30 [ t y p e ] => s t r i n g [ c l e P r i m a i r e ] => 0 [
n o t N u l l ] => 1 )
[ prenom ] => A r r a y (
[ l o n g u e u r ] => 30 [ t y p e ] => s t r i n g [ c l e P r i m a i r e ] => 0 [
n o t N u l l ] => 1 )
[ m o t _ d e _ p a s s e ] => A r r a y (
[ l o n g u e u r ] => 3 2 ] [ t y p e ] => s t r i n g [ c l e P r i m a i r e ] => 0 [
n o t N u l l ] => 1 )
[ a n n e e _ n a i s s a n c e ] => A r r a y (
[ l o n g u e u r ] => 11 [ t y p e ] => i n t [ c l e P r i m a i r e ] => 0 [ n o t N u l l ] => 0
) [ r e g i o n ] => A r r a y (
[ l o n g u e u r ] => 30 [ t y p e ] => s t r i n g [ c l e P r i m a i r e ] => 0 [
n o t N u l l ] => 0 )
)
Ces informations nous suffiront pour construire la classe générique Notez en particulier que l’on connaît le ou les attributs qui constituent la clé primaire (ici, l’e-mail) Cette information est indispensable pour chercher des données par clé ou effectuer des mises à jour Le constructeur de TableBD recherche donc le schéma de
la table-cible et initialise le tableau donnees avec des chaînes vides
f u n c t i o n _ _ c o n s t r u c t ( $ n o m _ t a b l e , $bd , $ s c r i p t = " moi " )
{
/ / I n i t i a l i s a t i o n d e s v a r i a b l e s p r i v é e s
$ t h i s−>bd = $bd ;
$ t h i s−>nom_table = $nom_table ;
/ / L e c t u r e du s c h é m a d e l a t a b l e , e t l a n c e r d ’ e x c e p t i o n s i
p r o b l è m e
$ t h i s−>schema = $bd−>schemaTable ( $nom_table ) ;
/ / On i n i t i a l i s e l e t a b l e a u d e s d o n n é e s
f o r e a c h ( $ t h i s−>schema a s $nom => $ o p t i o n s ) {
$ t h i s−>donnees [ $nom ] = " " ;
}
}
Le tableau des données est un simple tableau associatif, dont les clés sont les noms des attributs, et les valeurs de ceux-ci Après l’appel au constructeur, ce tableau des données est vide On peut l’initialiser avec la méthode nouveau(), qui prend en
Trang 3entrée un tableau de valeurs On extrait de ce tableau les valeurs des attributs connus dans le schéma, et on ignore les autres Comme l’indiquent les commentaires dans
le code ci-dessous, il manque de nombreux contrôles, mais l’essentiel de la fonction d’initialisation est là
/ ∗ ∗
∗ Méthode c r é a n t un n o u v e l o b j e t à p a r t i r d ’ un t a b l e a u
∗ /
p u b l i c f u n c t i o n nouveau ( $ l i g n e )
{
/ / On p a r c o u r t l e s c h é m a S i , p o u r un a t t r i b u t d o n n é ,
/ / u n e v a l e u r e x i s t e d a n s l e t a b l e a u : on l ’ a f f e c t e
f o r e a c h ( $ t h i s−>schema a s $nom => $ o p t i o n s )
{
/ / I l manque b e a u c o u p d e c o n t r ô l e s E t s i $ l i g n e [ $nom ] / / é t a i t un t a b l e a u ?
i f ( i s S e t ( $ l i g n e [ $nom ] ) )
$ t h i s−>donnees [ $nom ] = $ l i g n e [ $nom ] ;
}
}
Une autre manière d’initialiser le tableau des données est de rechercher dans
la base, en fonction d’une valeur de clé primaire C’est ce que fait la méthode chercherParCle()
p u b l i c f u n c t i o n c h e r c h e r P a r C l e ( $ c l e )
{
/ / Commençons p a r c h e r c h e r l a l i g n e d a n s l a t a b l e
$ c l a u s e W h e r e = $ t h i s−>a c c e s C l e ( $params , "SQL" ) ;
/ / C r é a t i o n e t e x é c u t i o n d e l a r e q u ê t e SQL
$ r e q u e t e = " SELECT ∗ FROM $ t h i s −>nom_table WHERE $clauseWhere
" ;
$ r e s u l t a t = $ t h i s−>bd−>execRequete ( $ r e q u e t e ) ;
$ l i g n e = $ t h i s−>bd−>l i g n e S u i v a n t e ( $ r e s u l t a t ) ;
/ / S i on n ’ a p a s t r o u v é , c ’ e s t q u e l a c l é n ’ e x i s t e p a s :
/ / on l è v e u n e e x c e p t i o n
i f ( ! i s _ a r r a y ( $ l i g n e ) ) {
t h r o w new E x c e p t i o n ( " TableBD : : c h e r c h e r P a r C l e La l i g n e n ’
e x i s t e p a s " ) ; }
/ / I l n e r e s t e p l u s qu ’ à c r é e r l ’ o b j e t a v e c l e s d o n n é e s du
t a b l e a u
$ t h i s−>nouveau ( $ l i g n e ) ;
r e t u r n $ l i g n e ;
}
La méthode reçoit les valeurs de la clé dans un tableau, constitue une clause WHERE (avec une méthode accesCle() que je vous laisse consulter dans le code
Trang 4lui-même), et initialise enfin le tableau des données avec la méthode nouveau(), vue précédemment Une exception est levée si la clé n’est pas trouvée dans la base Finalement, comment accéder individuellement aux valeurs des attributs pour une ligne donnée ? On pourrait renvoyer le tableau donnees, mais ce ne serait pas très pratique à manipuler, et romprait le principe d’encapsulation qui préconise de ne pas dévoiler la structure interne d’un objet
On pourrait créer des accesseurs nommés getNom (), ó nom est le nom de
l’attribut dont on veut récupérer la valeur C’est propre, mais la création un par un
de ces accesseurs est fastidieuse
PHP fournit un moyen très pratique de résoudre le problème avec des méthodes
dites magiques Elles permettent de coder une seule fois les accesseurs get et set, et
prennent simplement en entrée le nom de l’attribut visé Voici ces méthodes pour notre classe générique
/ ∗ ∗
∗ Méthode " m a g i q u e " g e t : r e n v o i e un é l é m e n t du t a b l e a u
∗ de d o n n é e s
∗ /
p u b l i c f u n c t i o n _ _ g e t ( $nom )
{
/ / On v é r i f i e q u e l e nom e s t b i e n un nom d ’ a t t r i b u t du s c h é m a
i f ( ! i n _ a r r a y ( $nom , a r r a y _ k e y s ( $ t h i s−>schema ) ) ) {
t h r o w new E x c e p t i o n ( " $nom n ’ e s t p a s un a t t r i b u t de l a
t a b l e $ t h i s−>nom_table " ) ;
}
/ / On r e n v o i e l a v a l e u r du t a b l e a u
r e t u r n $ t h i s−>donnees [ $nom ] ;
}
/ ∗ ∗
∗ Méthode " m a g i q u e " s e t : a f f e c t e une v a l e u r à un é l é m e n t
∗ du t a b l e a u de d o n n é e s
∗ /
p u b l i c f u n c t i o n _ _ s e t ( $nom , $ v a l e u r )
{
/ / On v é r i f i e q u e l e nom e s t b i e n un nom d ’ a t t r i b u t du s c h é m a
i f ( ! i n _ a r r a y ( $nom , a r r a y _ k e y s ( $ t h i s−>schema ) ) ) {
t h r o w new E x c e p t i o n ( " $nom n ’ e s t p a s un a t t r i b u t de l a
t a b l e $ t h i s−>nom_table " ) ;
}
/ / On a f f e c t e l a v a l e u r au t a b l e a u ( d e s c o n t r ơ l e s s e r a i e n t / / b i e n v e n u s )
$ t h i s−>donnees [ $nom ] = $ v a l e u r ;
}
Trang 5La méthode get(nom ) est appelée chaque fois que l’on utilise la syntaxe
$o->nom pour lire une propriété qui n’existe pas explicitement dans la classe Dans notre cas, cette méthode va simplement chercher l’entrée nom dans le tableau
de données La méthode set(nom, valeur ) est appelée quand on utilise la
même syntaxe pour réaliser une affectation Ces méthodes magiques masquent la structure interne (que l’on peut donc modifier de manière transparente) en évitant
de reproduire le même code pour tous les accesseurs nécessaires Il existe également
une méthode magique call(nom, params ) qui intercepte tous les appels à une
méthode qui n’existe pas
Contrôles, insertion et mises à jour
Maintenant que nous savons comment manipuler les valeurs d’un objet associé à une ligne de la table, il reste à effectuer les contrôles et les mises à jour La méthode controle() vérifie les types de données et la longueur des données à insérer La contrainte de généricité interdit d’aller bien plus loin
p r o t e c t e d f u n c t i o n c o n t r o l e ( )
{
/ / On commence p a r v é r i f i e r l e s t y p e s d e d o n n é e s
f o r e a c h ( $ t h i s−>schema a s $nom => $ o p t i o n s ) {
/ / C o n t r ô l e s e l o n l e t y p e d e l ’ a t t r i b u t
i f ( $ o p t i o n s [ ’ t y p e ’ ] == " s t r i n g " ) {
/ / C ’ e s t u n e c h a î n e d e c a r a c t è r e s V é r i f i o n s s a t a i l l e
i f ( s t r l e n ( $ t h i s−>donnees [ $nom ] ) > $ o p t i o n s [ ’ l o n g u e u r ’ ] )
{
$ t h i s−> e r r e u r s [ ] = " La v a l e u r pour $nom e s t t r o p longue
" ;
r e t u r n f a l s e ;
} }
e l s e i f ( $ o p t i o n s [ ’ t y p e ’ ] == " i n t " ) {
/ / I l f a u t q u e c e s o i t un e n t i e r
i f ( ! i s _ i n t ( $ t h i s−>donnees [ $nom ] ) ) {
$ t h i s−> e r r e u r s [ ] = "$nom d o i t ê t r e un e n t i e r " ;
r e t u r n f a l s e ;
} }
r e t u r n t r u e ;
}
}
Les méthodes d’insertion et de mise à jour fonctionnent toutes deux sur le même principe On construit dynamiquement la requête SQL (INSERT ou UPDATE), puis on l’exécute L’exemple de l’insertion est donné ci-dessous Bien entendu on exploite le schéma de la table pour connaître le nom des attributs, et on trouve les valeurs dans
le tableau de données
p u b l i c f u n c t i o n i n s e r t i o n ( )
{
/ / I n i t i a l i s a t i o n s
$noms = $ v a l e u r s = $ v i r g u l e = " " ;