Pour les débutants. langage de manipulation des données



Documents pareils
Pour les débutants. langage de définition des données

Bases de Données relationnelles et leurs systèmes de Gestion

CREATION WEB DYNAMIQUE

Olivier Mondet

Le Langage De Description De Données(LDD)

PHP 5. La base de données MySql. A. Belaïd 1

Le langage SQL pour Oracle - partie 1 : SQL comme LDD

Création et Gestion des tables

Le langage SQL (première partie) c Olivier Caron

Les BASES de DONNEES dans WampServer

TP3 : Creation de tables 1 seance

TP Contraintes - Triggers

Langage SQL : créer et interroger une base

1. Qu'est-ce que SQL? La maintenance des bases de données Les manipulations des bases de données... 5

Bases de données relationnelles

I. MySQL : Serveur et SGBD

1 Introduction et installation

Modélisation et Gestion des bases de données avec mysql workbench

Langage SQL (1) 4 septembre IUT Orléans. Introduction Le langage SQL : données Le langage SQL : requêtes

NFA 008. Introduction à NoSQL et MongoDB 25/05/2013

Licence de MIDO - 3ème année Spécialités Informatique et Mathématiques Appliquées

Bible MySQL! La première version de MySQL est apparue en Cette première version est créée pour un usage personnel à partir de msql.

DOSSIER D'ACTIVITES SUR LE PHP N 03 Créer une base de données MySQL avec PHPMyAdmin

Installation d'un serveur FTP géré par une base de données MySQL

Chapitre 3 LE MODELE RELATIONNEL ET SQL (DDL)

Objectifs du TP : Initiation à Access

PHP et mysql. Code: php_mysql. Olivier Clavel - Daniel K. Schneider - Patrick Jermann - Vivian Synteta Version: 0.9 (modifié le 13/3/01 par VS)

COMMANDES SQL... 2 COMMANDES DE DEFINITION DE DONNEES... 2

1. Base de données SQLite

SQL Historique

Stockage du fichier dans une table mysql:

BIRT (Business Intelligence and Reporting Tools)

clef primaire ; clef étrangère ; projection ; restriction ; jointure ; SQL ; SELECT ; FROM ; WHERE

Introduction au Système de Gestion de Base de Données et aux Base de Données

ECR_DESCRIPTION CHAR(80), ECR_MONTANT NUMBER(10,2) NOT NULL, ECR_SENS CHAR(1) NOT NULL) ;

Bases de données élémentaires Maude Manouvrier

Pratique et administration des systèmes

1 Position du problème

A QUOI SERVENT LES BASES DE DONNÉES?

Auto-évaluation Oracle: cours de base

Historisation des données

Encryptions, compression et partitionnement des données

Partie 0 : Gestion des tablespace et des utilisateurs... 3

I4 : Bases de Données

Les bases de données

Compétences Business Objects

Plan. Bases de Données. Sources des transparents. Bases de SQL. L3 Info. Chapitre 4 : SQL LDD Le langage de manipulation de données : LMD

Tutorial sur SQL Server 2000

SQL sous SqlServer OLIVIER D. DEHECQ Olivier 0

1/ Présentation de SQL Server :

Langage propre à Oracle basé sur ADA. Offre une extension procédurale à SQL

PHP 4 PARTIE : BASE DE DONNEES

Guide d installation de MySQL

Procédures Stockées WAVESOFT ws_sp_getidtable Exemple : ws_sp_getnextsouche Exemple :... 12

NOTICE D UTILISATION

Cours: Administration d'une Base de Données

Plan Général Prévisionnel (1/2) (non contractuel) Internet et Outils L1/IO S2-IO2 Bases de données: Jointures, Transactions

Construction d un EDD avec SQL 2008 R2. D. Ploix - M2 Miage - EDD - Création

A QUOI SERVENT LES BASES DE DONNÉES?

INSTITUT NATIONAL DES TELECOMMUNICATIONS CONTROLE DES CONNAISSANCES. 2. Les questions sont indépendantes les unes des autres.

ISC Système d Information Architecture et Administration d un SGBD Compléments SQL

Table des matières L INTEGRATION DE SAS AVEC JMP. Les échanges de données entre SAS et JMP, en mode déconnecté. Dans JMP

Gestion de base de données

Intégrité sémantique dans les bases de données relationnelles

Bases de données relationnelles & SQL

PHP. Bertrand Estellon. 26 avril Aix-Marseille Université. Bertrand Estellon (AMU) PHP 26 avril / 214

Application web de gestion de comptes en banques

Manuel d utilisateur du site de covoiturage «Etucovoiturage»

Intégrité des données

Access et Org.Base : mêmes objectifs? Description du thème : Création de grilles d écran pour une école de conduite.

MySQL / SQL EXEMPLES

Raja Bases de données distribuées A Lire - Tutoriel

Système de Gestion de Bases de Données Relationnelles. MySQL. Youssef CHAHIR

Dans l'article précédent, vous avez appris

GEST_INSTANCES APPLICATION DE GESTION DES INSTANCES ET REUNIONS EN EPLE ETABLISSEMENT PUBLIC LOCAL D ENSEIGNEMENT

Mysql avec EasyPhp. 1 er mars 2006

WEB DEVELOPER SGBD SYSTEME DE GESTION DE BASES DE DONNEES L étudiant sera capable :

SQL. Oracle. pour. 4 e édition. Christian Soutou Avec la participation d Olivier Teste

Tutoriel Drupal version 7 :

Module Com231A - Web et Bases de Données Notion 5 : Formulaires et utilisation des Bases de Données avec PHP

Devoir Data WareHouse

ContactForm et ContactFormLight - Gestionnaires de formulaire pour Prestashop Edité par ARETMIC S.A.

Les Triggers SQL. Didier DONSEZ. Université de Valenciennes Institut des Sciences et Techniques de Valenciennes

laposte.net) Ministère de l'éducation nationale Atelier sécurité Rabat RALL 2007

SUPPORT DE COURS / PHP PARTIE 3

Mysql. Les requêtes préparées Prepared statements

Cours Bases de données 2ème année IUT

Tous les autres noms de produits ou appellations sont des marques déposées ou des noms commerciaux appartenant à leurs propriétaires respectifs.

FORMATION A L UTILISATION DE PMB QUELQUES NOTIONS DE SQL

Notes de cours : bases de données distribuées et repliquées

14/04/2014. un ensemble d'informations sur un sujet : exhaustif, non redondant, structuré, persistant. Gaëlle PERRIN SID2 Grenoble.

Sommaire. I.1 : Alimentation à partir d un fichier Access (.mdb)...2

OpenPaaS Le réseau social d'entreprise

Comment Connecter une Base de Données MySQL via un Driver JDBC Avec OpenOffice.org

Comment mettre en ligne un site WordPress local

Transcription:

Pour les débutants SQL : langage de manipulation des données Les bases de données sont très utilisées dans les applications Web. La création, l interrogation et la manipulation des données de la base sont réalisées en SQL. Dans cette série d articles vous apprendrez le langage SQL ainsi que les bases nécessaires pour communiquer avec une base de données à partir d un script PHP. Cet article explique : Comment insérer des données. Comment les mettre à jour ou les supprimer. Comment les afficher. Ce qu il faut savoir : Aucun prérequis. Dans l article précédent, sur le langage de définition des données, vous avez appris à créer une base et des tables. Vous allez maintenant apprendre à insérer des données dans cette base, à les modifier ou à les supprimer tout en tenant compte des contraintes établies. Pour appliquer les notions présentées, vous devez utiliser un serveur de base de données MySQL, de préférence la version 5, un serveur web avec PHP version 5 et le client graphique phpmyadmin. Les distributions XAMPP (Windows, Linux, Mac OS), WAMP (Windows), EasyPHP (Windows) ou MAMP (Mac OS) vous fourniront l environnement de travail nécessaire. Dans cet article, nous allons utiliser l exemple d une bibliothèque privée dont le schéma est représenté par la Figure 1. Le Listing 1 donne les instructions SQL de création de tables. Insérer une ligne de données La commande SQL INSERT permet d insérer des données dans une table. Il faut préciser le nom de la table et éventuellement la liste des colonnes dans lesquelles les données vont être insérées. La première valeur indiquée sera liée au nom de la première colonne listée, la seconde valeur à la seconde colonne, etc... La commande suit la syntaxe : INSERT INTO nom _ table (col1, col2,...) VALUES (val1, val2,...); Type de données Lorsque la valeur insérée est de type chaîne de caractères, il faut indiquer la valeur entre quotes. Par exemple, pour insérer un nom dans la colonne nom de la table auteur, la valeur 'Tolkien' est utilisée. Les nombres Figure 1. Schéma de la base de données biblio 40 11/2010

SQL sont entrés tels quels. Par exemple, la colonne clé primaire id_auteur prend la valeur 7. Les dates doivent suivre un format prédéfini (YYYY-MM-DD) et être écrites entre quotes. Tolkien est né un 03 janvier 1892 ce qui se traduit en MySQL par : '1892-01-03'. Pour signaler l absence d information, il suffit d utiliser la valeur NULL, sans quotes afin qu elle ne soit pas considérée comme une chaîne de caractères, comme dans l exemple suivant : INSERT INTO auteur (id _ auteur, nom, prenom, date _ naissance) VALUES (7,'Tolkien',NULL,'1892-01-03'); La valeur NULL ne doit pas être confondue avec la chaîne vide ou le chiffre 0. Elle est utilisée pour symboliser l absence d information. Ordre d insertion Si toutes les colonnes sont renseignées, il n est pas nécessaire de les lister dans la commande. Dans ce cas, il faut donner les valeurs dans l ordre de déclaration des colonnes. Par exemple, dans la table auteur, l instruction suivante est équivalente à celle proposée ci-dessus : INSERT INTO auteur VALUES (7,'Tolkien',NULL,'1892-01-03'); Lister le nom des colonnes permet d insérer des valeurs dans un ordre différent de celui de la déclaration dans la table. L exemple suivant est équivalent aux deux requêtes précédentes : INSERT INTO auteur (nom, prenom, id _ auteur, date _ naissance) VALUES ('Tolkien',NULL,7,'1892-01-03'); Clés primaires et uniques La déclaration d une colonne comme clé primaire ou unique implique qu elle ne peut pas contenir deux valeurs identiques. Toute requête dans ce sens sera rejetée. L instruction suivante cherche à entrer un autre auteur ayant 7 comme clé primaire ce qui provoquera une erreur : INSERT INTO auteur VALUES (7,'Hugo','Victor','1802-02-26'); #1062 - Duplicate entry '7' for key 'PRIMARY' Listing 1. Création tables -- selectionner la base de travail USE biblio; -- creer les tables CREATE TABLE zone ( code _ zone CHAR(10) NOT NULL, piece VARCHAR(20), meuble VARCHAR(20), CONSTRAINT pk _ zone PRIMARY KEY (code _ zone) CREATE TABLE livre ( isbn CHAR(20) NOT NULL, titre VARCHAR(30) NOT NULL, genre ENUM('roman','policier','theatre','historique', 'fantastique'), date _ parution INTEGER, langue ENUM('francais','anglais','allemand','espagnol', 'chinois') DEFAULT 'francais', nb _ pages INTEGER UNSIGNED, preface ENUM('oui','non'), code _ zone CHAR(10), CONSTRAINT pk _ livre PRIMARY KEY (isbn), CONSTRAINT fk _ zone FOREIGN KEY (code _ zone) REFERENCES zone(code _ zone) ON DELETE SET NULL ON UPDATE CASCADE CREATE TABLE auteur ( id _ auteur INTEGER NOT NULL AUTO _INCREMENT, nom VARCHAR(45) NOT NULL, prenom VARCHAR(45), date _ naissance DATE, CONSTRAINT pk _ auteur PRIMARY KEY (id _ auteur) CREATE TABLE ecrit ( isbn CHAR(20) NOT NULL, id _ auteur INTEGER NOT NULL, CONSTRAINT pk _ ecrit PRIMARY KEY (isbn, id _ auteur), CONSTRAINT fk _ livre FOREIGN KEY (isbn) REFERENCES livre (isbn) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT fk _ auteur FOREIGN KEY (id _ auteur ) REFERENCES auteur (id _ auteur) ON UPDATE CASCADE Tableau 1. Contenu de la table ZONE code_zone piece meuble c10 chambre armoire en pin c20 chambre armoire en pin s8 salon bibliotheque noire c5 chambre bibliotheque grise Limite de champs Lors de l insertion d une valeur qui sort des limites autorisées par le domaine du champ et ses contraintes, le SGBD doit refuser l opération. Le comportement de MySQL dépend du mode défini dans le fichier de configuration (my.ini ou my.cnf selon le système d exploitation). Par défaut, MySQL attribue la valeur de la borne la plus proche d un champ numérique, ou tronque les chaînes de caractères. Pour éviter cela, il faut indiquer que le mode du SGBD doit être strict (sql_mode = strict_all_tables). Par exemple, l insertion d un nombre de pages négatif dans la table livre enregistrera la valeur 0 par défaut ou refusera l insertion en mode strict : INSERT INTO livre (isbn, titre, genre, date_parution, langue, nb_pages) VALUES ('102-2-35419-5','Les fourmis','roman',1991,'francais',-300); #1264 - Out of range value for column 'nb_pages' at row 1 www.phpsolmag.org 41

Pour les débutants Tableau 2. Contenu de la table LIVRE isbn titre genre date_parution langue nb_pages preface code_zone 128-5-56985-5 Fall of giants historique 2010 anglais 255 oui c20 598-5-55596-2 Notre Dame de Paris roman 1831 francais 123 non s8 102-2-35419-5 Les fourmis roman 1991 francais 300 NULL c10 523-5-65472-9 David Copperfield roman 1850 anglais 458 oui s8 320-2-02365-5 Le bourgeois gentilhomme theatre 1670 francais 152 NULL NULL 152-5-55695-2 Le seigneur des anneaux fantastique 1954 francais NULL NULL NULL Tableau 3. Contenu de la table ZONE après mise à jour code_zone piece meuble c20 chambre armoire en pin s11 salon bibliotheque noire c5 chambre bibliotheque grise Insérer un sous-ensemble de données Pour ne renseigner qu un sous-ensemble de colonnes, il suffit de les lister dans la commande INSERT. Les valeurs non renseignées seront gérées automatiquement par le SGBD : un nouveau numéro en cas d'auto incrémentation, NULL, une valeur prédéfinie par défaut lors de la création de la table... Valeur par défaut Si une valeur par défaut a été attribuée à une colonne lors de la création de la table, cette valeur sera utilisée si la colonne n est pas renseignée. Dans la table livre, la colonne langue prend la valeur 'francais' par défaut. Aussi, si aucune langue n est définie dans l instruction, la valeur prise par le champ langue sera le français : INSERT INTO livre (isbn, titre, genre, date_parution, nb_pages, code_zone) VALUES ('320-2-02365-5','Le bourgeois gentilhomme','theatre',1670,152,null); Null / Not null Les colonnes non renseignées prendront automatiquement la valeur NULL sauf si une autre valeur par défaut a été définie. Par exemple, pour insérer un livre dont le nombre de pages, la présence de préface et le code zone sont inconnus, la requête suivante mettra automatiquement la valeur NULL dans le champ nb_pages, preface et code_zone de la table livre : INSERT INTO livre (isbn, titre, genre, date _ parution, langue) VALUES ('152-5-55695-2','Le seigneur des anneaux','fantastique',1954,'francais'); Attention, si la colonne concernée a été déclarée comme NOT NULL, l'insertion sera rejetée si le SG- BD a bien été placé en mode strict. Le cas échéant, l'insertion enregistrera une chaîne vide. Par exemple, dans la table livre, c'est le cas de la colonne titre. Nous travaillons ici en mode strict. L'instruction suivante va donc générer une erreur : INSERT INTO livre (isbn, genre, date _ parution, nb _ pages, code _ zone) VALUES ('598-5-55596-2','roman',1831,123,NULL); #1364 - Field 'titre' doesn't have a default value Auto incrément Lorsqu une colonne numérique a un auto incrément, elle n a pas à être renseignée. L insertion d une nouvelle ligne provoque l ajout automatique d une valeur dans la colonne. Celle-ci est égale à l entier immédiatement supérieur à la valeur maximale de la colonne. Dans la table auteur, la colonne id_auteur est auto incrémentée. L instruction suivante génère donc un identifiant automatiquement : INSERT INTO auteur (nom, prenom, date _ naissance) VALUES ('Hugo','Victor','1802-02-26'); Clé primaire Une colonne référencée comme clé primaire doit obligatoirement être renseignée (sauf si elle est auto incrémentée). Une instruction qui omet d entrer une clé primaire provoque une erreur. Si le numéro ISBN d un livre n est pas indiqué, l insertion est refusée : INSERT INTO livre (titre, genre, date_parution, langue, nb_pages, code_zone) VALUES ('David Copperfield','roman',1850,'anglais',458,NULL); #1364 - Field 'isbn' doesn't have a default value Insérer avec phpmyadmin L interface web phpmyadmin permet d insérer des données dans la base sans avoir de connaissances SQL. Elle présente l avantage d afficher la requête d insertion après exécution de cette dernière. Ceci permet de formuler des requêtes qui pourront être adaptées et utilisées dans un script PHP. Pour insérer des données dans une table, il faut sélectionner la table en cliquant sur son nom dans le 42 11/2010

SQL Tableau 4. Contenu de la table LIVRE après mise à jour isbn titre genre date_parution langue nb_pages preface code_zone 128-5-56985-5 Fall of giants historique 2010 anglais 255 oui c20 598-5-55596-2 Notre Dame de Paris roman 1831 francais 123 non s11 102-2-35419-5 Les fourmis roman 1991 francais 300 NULL s11 523-5-65472-9 David Copperfield roman 1850 anglais 458 oui s11 320-2-02365-5 Le bourgeois gentilhomme theatre 1670 francais 152 NULL NULL 152-5-55695-2 Le seigneur des anneaux fantastique 1954 francais NULL NULL NULL cadre de gauche de l interface. Le formulaire d insertion est disponible à partir de l onglet Insérer dans le cadre droit (Figure 2). Une fois le formulaire soumis, la requête est générée automatiquement, affichée et envoyée à MySQL. Extraire des données La commande SELECT extrait des données de la base. Dans cet article, vous allez apprendre à afficher toutes les données d une table. Dans les prochains numéros, vous verrez comment restreindre l affichage des données et comment réaliser des jointures entre plusieurs tables. Pour afficher toutes les données d une table, la commande suit la syntaxe suivante : SELECT * FROM nom _ table; Pour afficher la liste des auteurs enregistrés dans la base, il suffit de taper la commande suivante dans la console : SELECT * FROM auteur; Si vous utilisez phpmyadmin, il faut cliquer sur le nom de la table dans le cadre de gauche (Figure 3). Cette opération permet de vérifier que les insertions se sont bien déroulées. Mettre à jour des données Une fois les données insérées dans les tables, elles peuvent être modifiées grâce à la commande UPDATE. Celle-ci permet la modification d une ou plusieurs lignes d une table. Il est possible d indiquer les nouvelles valeurs pour plusieurs colonnes en les séparant par des virgules : UPDATE nom_table SET col1 = val1 [, col2 = val2,...]; Pour ajouter un an aux dates de parution des livres, il faut utiliser la commande : UPDATE livre SET date_parution = date_parution + 1; Toutes les lignes de la table livre seront concernées par la mise à jour. Pour restreindre la modification à un sous-ensemble de lignes, il faut utiliser la clause WHERE suivie d une condition. Seules les lignes qui satisfont la condition sont modifiées. Par exemple, pour mettre à jour seulement les livres en français : UPDATE livre SET date _ parution = date _ parution + 1 WHERE langue = 'francais'; Pour changer le genre du livre Les fourmis, il est possible d utiliser la commande suivante : UPDATE livre SET genre = 'fantastique' WHERE titre = 'Les fourmis'; Si plusieurs livres portaient ce nom dans la base, le genre aurait été modifié pour chacun. Pour éviter cette situation, il vaut mieux utiliser la clé primaire de l ouvrage car elle identifie une seule et unique ligne de la table : UPDATE livre SET genre = 'fantastique' WHERE isbn ='102-2-35419-5'; Lors de mises à jour, MySQL indique le nombre de lignes qui satisfont la condition (Rows matched) et le nombre de modifications effectuées (Changed). La mise à jour peut échouer dans plusieurs cas : la valeur ne correspond pas au type de données attendu, la valeur viole une contrainte (clé primaire, clé unique, clé étrangère), Attention, si vous n êtes pas en mode strict, l attribution de valeurs hors des bornes autorisées peut entraîner l enregistrement de fausses données (cf Insérer une ligne de données >>> Limite de champs). Dans phpmyadmin, lorsque vous avez affiché la liste des données de la table, vous pouvez en modifier le contenu en cliquant sur l icône en forme de crayon (Figure 3). Un formulaire identique à celui de l insertion est affiché pré rempli avec les valeurs de la ligne sélectionnée. L envoi du formulaire génère et affiche une requête UPDATE. Supprimer des données La commande SQL DELETE permet de supprimer des lignes dans une table. Pour restreindre la suppression, il faut indiquer une condition. www.phpsolmag.org 43

Pour les débutants Figure 2. PhpMyAdmin : formulaire d insertion et de modification Figure 3. PhpMyAdmin : liste des données de la table zone DELETE FROM nom _ table [WHERE condition]; Pour effacer le livre Notre Dame de Paris, il faut utiliser la commande : DELETE FROM livre WHERE isbn = '598-5-55596-2'; Attention, si vous n indiquez aucune condition, toutes les lignes de votre table seront supprimées. Dans phpmyadmin, l icône en forme de croix à côté du crayon permet de supprimer la ligne (Figure 3). Manipuler des clés étrangères Une clé étrangère peut prendre la valeur NULL ou une valeur issue de la clé primaire de la table qu elle référence. Cette restriction entraîne parfois des difficultés lors des insertions, des mises à jour ou des suppressions. Lors des insertions dans la base biblio, aucune valeur n a été attribuée aux clés étrangères. Pour les exemples suivants, les tables zone et livre comporteront les valeurs définies dans les tableaux 1 et 2. Ainsi, l attribution de la zone s10 au livre Les fourmis est refusée car le code_zone n existe pas dans la table zone : UPDATE livre SET code_zone = 's10' WHERE isbn = '102-2-35419-5'; #1452 - Cannot add or update a child row: a foreign key constraint fails ('biblio'.'livre', CONSTRAINT 'fk_zone' FOREIGN KEY ('code_zone') REFERENCES 'zone' ('code_zone') ON DELETE SET NULL ON UPDATE CASCADE) L attribution de la zone s8 qui existe ne pose pas de problème, ici pour le livre Les fourmis : UPDATE livre SET code _ zone = 's8' WHERE isbn = '102-2-35419-5'; 44 11/2010

Sur Internet http://www.mysql.fr MySQL, http://www.phpmyadmin.net phpmyadmin. Les propriétés indiquées lors de la création de la table (cf Article SQL : langage de définition des données) influent sur le comportement lors de mises à jour ou de suppressions de valeurs référencées (clauses ON UPDATE ou ON DELETE). Par exemple, la modification ou la suppression du code_zone dans la table zone entraînera une mise à jour automatique de la table livre grâce aux clauses ON UPDATE CASCADE et ON DELETE SET NULL. UPDATE zone SET code _ zone = 's11' WHERE code _ zone = 's8'; DELETE FROM zone WHERE code _ zone = 'c10'; SELECT * FROM livre; La commande SELECT affiche la table livre avec les valeurs s8 remplacées par s11 et la valeur c10 remplacée par NULL (tableaux 3 et 4). Si le comportement en cas de mise à jour ou de suppression de la valeur d'une colonne référencée n a pas été défini lors de la création de la table, aucune de ces opérations ne sera acceptée. Par exemple, sans clause ON DELETE SET NULL dans la table livre, la suppression du code_zone c10 aurait été refusée car utilisé dans la table livre. Par contre, la suppression de c5 aurait été autorisée car le code n est pas référencé ailleurs. Dans phpmyadmin, le formulaire d insertion ou de mise à jour d une table qui en référence une autre propose seulement les clés possibles pour les colonnes clés étrangères. Conclusion Vous avez appris dans cet article les bases du langage de manipulation de données : insertion, mise à jour, suppression et extraction globale d information. Dans le prochain numéro, vous apprendrez à affiner les extractions de données. CILIA MAURO, MAGALI CONTENSIN Cilia Mauro est gestionnaire de bases de données et développeur d applications web au CNRS. Elle enseigne les bases de données et PHP à l université. Contact : cilia.mro@gmail.com Magali Contensin est chef de projet en développement d applications au CNRS. Elle enseigne depuis plus de dix ans le développement d applications web à l université et est l auteur de nombreux articles sur le développement web en PHP. Contact : http://magali.contensin.online.fr Rejoignez le Club.PRO Rejoignez le Club.PRO Club.PRO www.phpsolmag.org 45