| Chapitre 10 |
Aller plus loin avec PHP |
|
PHP3 est un langage orienté objet. On dit
«orienté» car il n'implémente pas toutes les caractéristiques d'un pur
langage objet, mais permet de définir des classes.
Quel est l'interêt d'utiliser des classes? Sans rentrer
dans un débat «pour ou contre les langages à objets», il faut
reconnaitre que l'utilisation de classes permet des gains notables en
termes de productivité, de
réutilisabilité et de
maintenance.
Écrire une classe est sans doute un peu plus long que de coder
directement. En revanche, plus tard, le fait de n'accéder aux objets
que par leur interface
(encapsulation) permet une maintenance et des
évolutions plus aisées. Fermons là cette parenthèse.
L'écriture d'une classe en PHP3 commence par l'utilisation du mot
réservé Class suivi par le nom de la classe. Le bloc de code
suivant contient les variables membres et les méthodes
de la classe. L'exemple suivant définit une classe Point, ainsi les
méthodes pour déplacer ce point et pour obtenir sa position.
<?php
class Point {
// L'objet Point possède deux attributs, et
// trois méthodes, plus son constructeur
var $x, $y ;
// Constructeur avec valeurs par défaut
void function Point($posx=0, $posy=0) {
// $this-> est l'opérateur d'auto-référence
$this->x = $posx ;
$this->y = $posy ;
}
void function set($posx, $posy) {
$this->x = $posx ;
$this->y = $posy ;
}
void function move($deltax, $deltay) {
$this->x = $this->x + $deltax ;
$this->y = $this->y + $deltay ;
}
function get_pos(void) {
return array("posx"=>$this->x, "posy"=>$this->y);
}
}
// Utilisation des valeurs par défaut du Constructeur
$mypoint = new Point ;
$mypoint->set(5,10);
$mypoint->move(3, -2);
list($positionx, $positiony) = $mypoint->get_pos();
// Constructeur avec des paramètres
$another_one = new Point($positionx, $positiony);
// le point se trouve maintenant en 8, 8
?>
| 10.2 |
Utiliser des fonctions optionnelles |
|
Les extensions sont des fonctions PHP3 qui ne font pas partie
du langage de base, mais des fonctions optionnelles ajoutées au
langage sous la forme de bibliothèques dynamiques (.so sous
Linux/Unix et .dll sous Win32). Depuis une version récente de
PHP3, ces bibliothèques dynamiques sont toutes préfixées par
php3_. Elles doivent se trouver dans le répertoire désigné
par la directive extensions_dir du fichier de configuration
php3.ini.
Pour utiliser ces fonctions, vous avez le choix entre deux
possibilités. Soit ces fonctions sont utilisées dans presque toutes
vos pages PHP3, auquel cas vous pouvez spécifier dans
php3.ini le chargement de ces bibliothèques à chaque
lancement de l'interprêteur PHP3, soit ces fonctions ne sont utilisées
qu'occasionnellement dans quelques pages (génération d'images
GIF ou de fichier PDF) auquel cas leur
chargement systématique induirait une consommation inutile de
ressources. Dans ce second cas, la directive dl()
(dynamic load) en début de script force le
chargement à la demande. Lorsque PHP3 est utilisé en tant que module
du serveur Apache, il est possible (pour des questions de sécurité) de
désactiver le chargement dynamique des extensions par la directive
enable_dl de php3.ini.
En environnement Win32, l'ensemble des fonctions d'accès
aux sources de données (SGBD/R, ODBC, ...)
sont présents sous la forme d'extensions
dynamiques. Chaque script effectuant une connection base
de données doit donc charger la bibliothèque correspondante.
Dans les exemples suivants, nous utiliserons le chargement à le
demande, car il ne nécessite pas de modification de la configuration
de PHP3. En contexte multi-utilisateur (plusieurs développeurs sur le
même serveur HTTP et interprêteur PHP3), ceci permet à
chacun de sélectionner les extensions dont il a besoin.
L'exemple de code suivant va utiliser l'extension php3_gd.so
(php3_gd.dll sous Win32), ce qui sera l'occasion de parler
briévement des headers HTTP et des types
MIME. Nous allons détailler le code permettant de générer
à le demande un bouton dont les dimensions, la couleur de fond, et le
texte seront fournis en paramètre à l'appel. Ensuite, puisque nous
savons maintenant écrire des classes, nous écrirons une classe pour
encapsuler le tout et le rendre plus facilement réutilisable, sous la
forme d'un include.
Qu'allons nous réaliser ? Nous voulons un script qui génère une image
GIF dont la hauteur, la largeur, la couleur de fond, ainsi
que le libellé soient passés en paramètre à l'appel.
| 10.2.1 |
Les paramètres d'appel |
|
Comment récupérer les paramètres d'appel? Dans cet exemple nous
recevons les paramètres sous la forme d'une URL longue
(nous verrons dans le paragraphe consacré aux formulaires comment
récupérer les valeurs saisies par un utilisateur dans un formulaire).
Cette question est intéressante car ce besoin est très courant. Les
différents paramètres que nous allons passer seront optionnels. En
l'absence d'un des paramètres, une valeur par défaut sera utilisée.
Nous pourrons donc utiliser notre script de la façon suivante :
<IMG SRC="GenButton.php3?msg=PHP3+est+install%E9+correctement
&colorname=yellow&witdh=220&height=34">
ou encore :
<IMG SRC="GenButton.php3?msg=21170+Hits&colorname=Navy">
ou simplement :
<IMG SRC="GenButton.php3?msg=Hello+World">
Le code permettant de retrouver les différents paramètres a été adapté
d'un exemple également écrit par Claus Radloff
(Counter.php). Allez, on plonge! (les numéros de ligne ne
sont là que pour faciliter les explications)
1 $query_string = getenv("QUERY_STRING");
2
3 $env_array = split("&", $query_string);
4
5 while (list($key, $val) = each($env_array))
6 {
7 list($name, $value) = split("=", $val);
8
9 $name = urldecode($name);
10 $value = urldecode($value);
11
12 $$name = trim($value) ;
13 }
Tout d'abord, en ligne 1, nous stockons dans la variable
$query_string
le contenu de la partie Query de l'URL longue. Cette
variable d'environnement fait partie des spécifications liées aux CGI.
Dans un CGI, les paramètres sont passés sous la forme d'une
URL longue. Ils sont passés sous la forme d'un couple
nom_de_variable=valeur. Les couples variable/valeur sont
séparés par un &. Pour résoudre les problèmes de codage de
jeux de caractères entre le client (Win16, Win32, Mac, Linux,Unix,
Amiga, TI-57) et le serveur (Win32 ou Unix/Linux en ce qui nous
concerne) dans les valeurs de type chaîne de caractères, les espaces
sont remplacés par des +, et tous les caractères accentués
sont remplacés par identifiants normalisés. Par exemple, un é
sera passé sous la forme %E9. Le codage et le décodage de
ces chaînes est assuré par les fonctions PHP3 urlencode() et
urldecode().
La ligne 3 découpe la QUERY_STRING en
tokens séparés par le caractère \&. La
ligne 5 est une boucle pour chaque paramètre de
type «variable=valeur». La ligne 7 assigne à $name le
nom de la variable et à $value sa valeur. Les lignes 9
et 10 réalisent les substitutions de caractères spéciaux de façon à
ce que %E9 devienne é.
La ligne 12 affecte à la variable dont le nom est
$name la valeur $valeur. C'est une petite ruse bien
pratique en PHP3 : les «variables variables». Pour plus de précisions,
voir la doc. officielle de PHP3 sur ce sujet :
ou, en français :
Dans notre exemple, cela va avoir pour effet de créer une variable
$msg contenant "PHP3 est installé correctement".
| 10.2.2 |
Décomposer une couleur en composantes RGB |
|
Nous venons de dire que la couleur de fond sera passée par son nom.
Pour la concision de l'exemple, les couleurs possibles seront limitées
à celles définies en HTML 3.2, mais on pourrait utiliser l'ensemble
des couleurs définies par X11 (dans le rgb.txt). Pour récupérer les
valeurs des composantes Rouge, Verte et Bleue pour une couleur donnée,
nous utiliserons un tableau associatif dérivé de Colors.php
de Claus Radloff (téléchargeable sur Berber's PHP3 Examples page
(http://webdev.berber.co.il/), partie «Graphics»).
Voici comment cela fonctionne (Après avoir lu le paragraphe sur les
tableaux associatifs, ça ne devrait pas vous poser de problème).
// Extrait de Colors.php par Claus Radloff.
// On créée une correspondance entre le nom et les composantes RGB
$coltable = Array (
"black"=>array("red"=>0x00, "green"=>0x00, "blue"=>0x00),
"maroon"=>array("red"=>0x80, "green"=>0x00, "blue"=>0x00),
"green"=>array("red"=>0x00, "green"=>0x80, "blue"=>0x00),
...
"aqua"=>array("red"=>0x00, "green"=>0xFF, "blue"=>0xFF),
"white"=>array("red"=>0xFF, "green"=>0xFF, "blue"=>0xFF)
) ;
Le tableau $coltable
est un tableau associatif qui comporte comme clé le nom de la couleur,
et comme valeur un tableau associatif ayant pour clé le nom de le
composante red, green ou blue, et comme valeur,
la valeur de cette composante exprimée de 0 à 255.
Ainsi, pour obtenir les valeurs des composantes RGB de la couleur
aqua, on procède comme suit :
$mycol = $coltable["aqua"];
$red = $mycol["red"];
$green = $mycol["green"];
$blue = $mycol["blue"];
| 10.2.3 |
Générer et retourner une image GIF |
|
Un script générant une image GIF ne fait que retourner à son apellant
le contenu binaire au format GIF en précisant dans l'entête HTTP le
type MIME «image/gif». Aussi, si votre PHP3 est configuré
pour afficher les erreurs directement dans le flux HTML, en cas
d'erreur, vous ne verrez pas le message d'erreur s'afficher. Il est
donc recommandé dans ce cas de paramétrer le php3.ini de
façon à ce que les logs d'erreur s'écrivent dans un fichier dédié, ou
dans l'observateur d'évènements de WinNT. Pour cela, mettre
display_errors à Off dans php3.ini. Un
script générant une image GIF ne doit rien retourner ni afficher en
dehors du contenu au format GIF.
Le reste du script est trivial. Pour tenter de garder un listing le
plus court possible, les vérifications ont été réduites au strict
minimum. Il y a certainement beaucoup de tests que vous voudrez
ajouter (message trop long, ...) pour utiliser ce script dans un
environnement de production. Voici donc le listing complet sans autre
commentaire.
<?php
//
// GenButton.php3
// Inspiré de nombreux autres exemples trouvés sur le Web.
//
// Chargement dynamique de la lib GD
dl('php3_gd.so');
// Pour Win32 : remplacer par dl('php3_gd.dll');
Header('Content-type: image/gif');
// Extrait de Colors.php par Claus Radloff.
$coltable = Array (
"black"=>array("red"=>0x00, "green"=>0x00, "blue"=>0x00),
"maroon"=>array("red"=>0x80, "green"=>0x00, "blue"=>0x00),
"green"=>array("red"=>0x00, "green"=>0x80, "blue"=>0x00),
"olive"=>array("red"=>0x80, "green"=>0x80, "blue"=>0x00),
"navy"=>array("red"=>0x00, "green"=>0x00, "blue"=>0x80),
"purple"=>array("red"=>0x80, "green"=>0x00, "blue"=>0x80),
"teal"=>array("red"=>0x00, "green"=>0x80, "blue"=>0x80),
"gray"=>array("red"=>0x80, "green"=>0x80, "blue"=>0x80),
"silver"=>array("red"=>0xC0, "green"=>0xC0, "blue"=>0xC0),
"red"=>array("red"=>0xFF, "green"=>0x00, "blue"=>0x00),
"lime"=>array("red"=>0x00, "green"=>0xFF, "blue"=>0x00),
"yellow"=>array("red"=>0xFF, "green"=>0xFF, "blue"=>0x00),
"blue"=>array("red"=>0x00, "green"=>0x00, "blue"=>0xFF),
"fuchsia"=>array("red"=>0xFF, "green"=>0x00, "blue"=>0xFF),
"aqua"=>array("red"=>0x00, "green"=>0xFF, "blue"=>0xFF),
"white"=>array("red"=>0xFF, "green"=>0xFF, "blue"=>0xFF)
) ;
$query_string = getenv("QUERY_STRING");
$env_array = split("&",$query_string);
while (list($key,$val) = each($env_array))
{
list($name,$value) = split("=",$val);
$name = urldecode($name);
$value = urldecode($value);
$$name = trim($value) ;
}
// Largeur mini = 150 pixels
if ($width<150) {
$width=150 ;
}
// Hauteur mini = 25 pixels
if ($height<25) {
$height=25 ;
}
// Couleur de fond par défaut : Gris "silver"
if ($colorname=="") {
$colorname="silver";
}
// Pas de message fourni ? Bizarre...
if ($msg=="") {
$msg = "<Empty>";
}
$img = ImageCreate($width,$height);
$bgcol = $coltable[$colorname];
$red = $bgcol["red"];
$green = $bgcol["green"];
$blue = $bgcol["blue"];
$bgcolor = ImageColorAllocate($img,$red,$green,$blue);
// On peut soit utiliser une fonte blanche ou noire en
// fonction de la couleur du fond...
/*
if ((($red+$blue+$green)/3) > 127) {
$fontcolor = ImageColorAllocate($img,0,0,0);
} else {
$fontcolor = ImageColorAllocate($img,255,255,255);
}
*/
// ...soit utiliser la couleur complémentaire
$fontcolor = ImageColorAllocate($img,(255-$red),
(255-$green),
(255-$blue));
ImageFill($img,1,1,$bgcolor);
// Très approximatif... juste pour l'exemple
$posx = (ImageSX($img)-7.5*strlen($msg))/2;
$posy = $height/2-6 ;
ImageString($img,3,$posx,$posy,$msg,$fontcolor);
ImageGif($img);
ImageDestroy($img);
?>
La bibliothèque GD permet de réaliser tous les graphiques utiles avec
une grande qualité est une facilité remarquable.
| 10.3 |
Utilisation de Formulaires |
|
Créer des sites Web présentant un contenu interactif suppose la
plupart du temps de fournir aux utilisateurs le moyen d'effectuer des
recherches, de sélectionner des articles par catégorie, de trier des
articles suivant différents critères. Le HTML 3.2 fournit tout ce qui
est nécessaire pour constituer des formulaires.
Qu'est-ce qu'un formulaire ? C'est une page pouvant contenir des
champs de saisie, des cases à cocher, des
listes, des zones de saisie de
texte et un bouton permettant de déclencher un traitement du côté du
serveur.
(le formulaire ci-dessous est inactif, il ne sert qu'à titre
d'illustration : Si vous appuyez sur le bouton de recherche, vous
verrez s'afficher l'URL longue dans la zone d'adresse de votre
navigateur. Faites "Back" ensuite).
Bien sûr, les différentes rubriques et langues présentes dans les
combo-box pourront être lues depuis des tables
de référence dans une base de données. Le
formulaire sera alors lui même généré par PHP3. Cet aspect concernant
l'interfaçage avec un SGBD est traité au paragraphe
suivant (voir 11).
Nous allons maintenant nous intéresser à la façon dont on peut
récupérer les valeurs spécifiées par l'utilisateur.
La première méthode est celle que nous avons utilisée dans notre
exemple de génération de bouton, utilisant la variable d'environnement
QUERY_STRING. Cela fonctionne, mais il faut avouer que (sans
être spécialement paresseux) avoir à écrire cette boucle de traitement
pour chaque formulaire est plutôt une chose fastidieuse.
Une fois de plus, PHP3 vient à notre secours et met en place d'office
les mécanismes permettant de propager les paramètres et leur valeur au
script de traitement du formulaire.
Une première possibilité est d'utiliser la fonctionnalité
track_vars. Elle est activée par une option dans le fichier
php3.ini ou en début de script par la directive
php_track_vars.
Dans ce cas la récupération des paramètres s'effectue comme suit :
<?php
// début du script, chargements dynamiques
// et initialisations diverses
$cdrubrique = $HTTP_POST_VARS["rubrique"] ;
$cdlangue = $HTTP_POST_VARS["langue"] ;
$strkwords = $HTTP_POST_VARS["kwords"] ;
// Lancement de la requête de recherche
// basée sur les critères utilisateur
?>
PHP3 gère automatiquement le contenu des tableaux associatifs
$HTTP_POST_VARS et $HTTP_GET_VARS
en fonction
du type de méthode POST ou GET utilisée dans le formulaire.
Pour en savoir plus sur l'utilisation des formulaires en HTML, le
choix de la méthode GET ou POST, faites un tour du
côté de la FAQ
(http://www.hut.fi/u/jkorpela/forms/). Ce lien contient
pratiquement tout sur le sujet.