FAQ fr.comp.lang.php
Mise à jour : 22 décembre 2008
Cette FAQ reprend les questions
posées régulièrement sur le newsgroup
fr.comp.lang.php (anciennement fr.comp.infosystemes.www.auteurs.php)
1. Présentation de la FAQ
Contenu de cette section
1.1 Mirroirs
Cette FAQ est également disponible sur
http://www.phpindex.com/fciwap/
1.2 Présentation des réponses :
Les questions prises en compte dans cette FAQ sont celles
directement liées à PHP, ainsi que quelques questions
limite ou hors sujet revenant régulièrement sur le
forum, indiquées par :
[HS](Hors Sujet)
[OT] (Off
Topic).
A chaque fois que possible, un lien direct vers les
versions traduite et originale du manuel approprié sera
fourni.
Tous les liens s'ouvriront dans une nouvelle fenêtre
(pour les navigateurs qui le supportent).
Toute réponse
mettant en jeu du code PHP sera accompagnée d'un exemple,
testé par le rédateur de la réponse sauf mention
contraire.
La "l" (lettre L") devant une variable
(exemple $l_dad) indique une variable locale à la fonction, ce
qui est bien entendu seulement une convention de nommage.
Le
terme "unix" n'est pas restreint à linux.
1.3 Charte et modération
Le forum fr.comp.lang.php est un forum modéré. Il est donc normal d'observer un délai avant la parution de votre article.
Pour être publiés, vos articles doivent se conformer à la Charte de ce forum, disponible sur http://www.usenet-fr.net/fur/chartes/comp.lang.php.html: la lecture de ce document est donc fortement conseillée.
Pour joindre les modérateurs, vous pouvez utiliser l'adresse moderateurs-php@listserv.usenet-fr.net en n'oubliant pas de joindre l'article auquel vous faites référence avec ses en-têtes complètes.
Il ne vous est pas interdit de rester poli et courtois : un refus de
publication est, sauf erreur, motivé par le respect de la Charte, ce
n'est ni une punition ni une insulte.
Que faire si votre article n'apparait pas au bout de 24h ? Si vous avez mis
une adresse email invalide, les modérateurs n'ont aucun moyen de vous prévenir que
votre article a été refusé. Dans TOUS les autres cas, vous recevrez, en cas
de refus, la raison pour laquelle votre article n'a pas été publié.
Donc si votre article n'est toujours pas publié après 24h et que votre
adresse FROM: ou REPLY-TO: est valide, le plus probable est que votre
article s'est perdu suite à une mauvaise configuration de votre serveur
de news. Prenez contact avec les modérateurs.
1.4 La différence avec alt.fr.comp.lang.php
Un peu plus d'un an après le passage en statut modéré de l'ancien
fr.comp.infosystemes.www.auteurs.php qui est devenu fr.comp.lang.php au
passage, la hiérarchie alt.* a vu l'ajout d'un équivalent de son
ancêtre (fciwap). La différence entre fclphp et alt.fclphp est que le
second n'est pas modéré. Avec dans les deux cas les avantages et
inconvénients de la modération ou de la non-modération.
1.5 Premiers rédacteurs de cette FAQ
(Par ordre alphabétique)
Thierry André,
thierry.andre@freesbee.fr,
@lias Théo
Thomas Broyer, étudiant,
ptittom@free.fr, alias (TOM) ou
Tom. aka M. RTFM
echoes@free.fr
alias Echoes
Armel Fauveau, Webmaster PHPIndex,
webmaster@phpindex.com
John Gallet, Ingénieur EFREI, john.gallet@wanadoo.fr,
aka M. Off Topic
1.6 Remerciements
- à François Boudot pour son script permettant
l'indexation automatique qui a bien servi avant la migration vers
phpFAQTory
- à Armel pour phpFAQTory
- aux personnes
nous ayant envoyé leurs remarques concernant ce document.
1.7 Points juridiques
Autorisation est donnée à quiconque le souhaite de
faire du "framing" pour afficher cette FAQ ou de la
recopier et de la diffuser sans la modifier, ni dans son contenu, ni dans sa forme.
N'hésitez pas
à nous contacter(voir plus bas le paragraphe maintenance) si vous avez besoin d'une autorisation pour
en citer des parties.
La totalité des informations
contenues dans cette FAQ est disponible sur internet et considérée
comme de notoriété publique.
Tous les noms de
produits et autres marques cités dans cette FAQ sont des
marques déposées par leurs propriétaires
respectifs.
L'intégralité du code cité est
le fruit de la rédaction des auteurs de cette FAQ, tiré
de code diffusé publiquement sur des forums de discussion ou
avec autorisation de l'auteur.
1.8 Maintenance de cette FAQ, remarques, liens rompus
Cette FAQ est maintenue par john.gallet@wanadoo.fr.
Vous pouvez lui soumettre des articles, lui signaler des erreurs, liens rompus (avec la nouvelle valeur si possible).
Contenu de cette
section
2. Les notions de base sur PHP
Contenu de cette section
2.1 Comment débuter en PHP
"Bienvenue chez les fous" :-) ((C)A.F. 1999)
PHP est
un langage simple tant dans sa syntaxe que dans ses fonctions. Il
faut connaître le HTML (ou l'apprendre en même temps).
L'achat des ouvrages indiqués dans la section ressources (en
bas de cette FAQ) est vivement conseillé. Installez PHP et
MySQL ou Postgres sur votre ordinateur par exemple avec le package
d'Emmanuel Faivre (windows) et testez vos scripts en local. Lisez ce
document, apprenez à lire le manuel de PHP, à chercher
un peu par vous même dans les multiples sites cités dans
cette FAQ, et à poser vos questions au bon endroit : fclphp
pour les questions liées à PHP,
news:fr.comp.applications.sgbd (fcas) pour les questions sur le langage
SQL ou la configuration de votre SGBDR (MySQL, Postgres, etc...) et
news:fr.comp.infosystemes.www.auteurs pour
les questions HTML , news:fr.comp.lang.javascript pour le JS, ainsi qu'au support technique (aide
en ligne, forums réservés) de votre hébergeur.
Partez du principe qu'il est probable que quelqu'un d'autre a déjà
été confronté au même problème : si
votre question n'est pas mentionnée dans cette FAQ, cherchez
sur les archives de ce NG : sur http://www.phpindex.com/ng/
ou sur google : http://groups.google.com
En respectant ces règles simples, vous aurez plus
rapidement une réponse pertinente à votre question.
2.2 php is not mysql !
Bien que la plupart des questions traitées dans ce document
concernent l'utilisation de PHP de concert avec une base de données,
et dans la plupart des cas MySQL, il est faux et restrictif de penser
que PHP nécessite un Système de Gestion de Base de
Données Relationnel (SGBDR), et encore plus faux de penser que
MySQL est "le" SGBDR incontournable avec PHP (on pourrait
déjà discuter longtemps du qualificatif de SGBDR pour
MySQL ...) : n'oublions pas Postgres, Oracle et Sybase pour ne citer
qu'eux.
De même, la majeure partie des questions sur fclphp
concernent l'utilisation de PHP couplé à un serveur web
(Apache, IIS, PWS, Xitami, NES, etc...) mais PHP peut tout à
fonctionner en tant qu'exécutable "stand-alone" :
c'est une application à part entière.
2.3 HTTP : client serveur en mode asynchrone
non connecté
Un script PHP utilisé pour générer
dynamiquement une page web, comme un script ASP par exemple,
s'exécute sur le serveur web qui reçoit une demande de
la part d'un navigateur client. Le script PHP va faire certaines
choses sur le serveur (mise à jour / interrogation de base de
données, écriture dans des fichiers sur le serveur,
consultation ou envoi de mail, etc...) puis va renvoyer au navigateur
le résultat (HTML, PNG...) de ses actions. La page HTML qui
revient vers le navigateur client n'a pas d'existence "physique",
elle n'est pas ce que l'on appelle une page "statique",
stockée sur le serveur (par FTP en général) et
"servie", identique, au navigateur client à la
demande. Néanmoins, en recevant le code HTML, le navigateur
n'a pas moyen de savoir que c'est une page dynamique ou statique : le
client ne sait rien de ce qui s'est passé sur le serveur où
tourne PHP.
Remarque importante car à la source de
nombreuses confusions :
En
particulier, du JavaScript qui
tourne sur cette page dans le navigateur client n'a aucun moyen de
savoir que PHP en a généré une partie. Ceci
implique que PHP peut passer des arguments à du JavaScript
(client), (en fait, on peut tout à fait faire du JS
dynamiquement généré par du PHP), mais également
que pour passer des arguments JS depuis le client vers PHP et donc le
serveur, il faudra soumettre un formulaire ou faire une redirection/un
refresh en JS qui appellera une URL en passant les valeurs JS en
argument. Bref, il faut bien que le client (JS) appelle le script PHP
serveur en lui passant les valeurs qui vont bien.
Notons ici
néanmoins que PHP peut ouvrir des connexions par sockets vers
d'autres serveurs.
2.4 Quel hébergeur choisir avec PHP ?
Hébergements payants : Reportez vous au site abc-hébergement :
http://www.abchebergement.com/
Si vous cherchez un hébergeur gratuit et vous voulez savoir quelles
extensions/fonctions php il propose, vous trouverez sur
http://www.centrale-lyon.org/ng/phpinfo.html
une liste d'hébergeurs proposant php gratuitement. On y trouve aussi des associations et des sociétés proposant
des formules à bas prix. Attention aux remarques en bas de la page avant de vous engager
pour 24 mois...
Un autre comparatif : http://cyberzoide.developpez.com/php4/hebergeurs/
2.5 Des problèmes d'installation
Voici une liste de pointeurs pour l'installation de PHP avec
différents serveurs web / SGBDR.
Avec windows :
Le package Easy-PHP (windows 9X/NT d'apache + mysql + php
+ phpmyadmin), est disponible à l'URL: http://www.easyphp.org/
A noter : il est plus judicieux de poser vos questions relatives
à ce package sur la mailing list reservée à cet
usage qui est en place sur http://www.easyphp.org/
Configuration du PWS pour PHP
Un guide complet,
pas à pas, avec captures d'écran :
http://davidubois.free.fr/cfg/index.html
Installation détaillée :
http://phm.nerim.net/wamp/Apache, MySQL et PHP sur un OS MS Windows 2000.
http://lwest.free.fr/doc/php/configuration_NT_fr.html php3 sur NT
Avec Unix :
De manière générale,
commencer par enlever tous les RPMs plus ou moins pre-intallés,
télécharger les tarballs et tout recompiler. Si vous
faites des installations sucessives, penser à commencer par un
make distclean ou carréement repartir des tarballs
d'origine.
Concernant SSL : il n'y a pas que mod-sll dans
la vie, on peut aussi compiler Apache avec support natif de SSL 128
bits. http://www.apache-ssl.org/
donne le détail du patch des sources et de la compilation.
Avec Sybase les options --with-sybase et
--with-sybase-ct ne doivent pas être utilisées ensemble
(conflit de la db et ct libs).
Avec Nescape Entreprise
Server sur Solaris
Lire le manuel :
http://fr2.php.net/manual/en/install.unix.sun.php
Avec Macintosh MacOS X
Deux packages sont
disponibles sur http://www.entropy.ch/software/macosx/php/
Traduction des procs d'install sur
http://www.mosx.net/logiciels/php_mysql.shtml
2.6 Editeurs PHP
Cette liste est fournie pour le confort des yeux.
N'importe
quel éditeur ASCII fait l'affaire.
Un article
complet rédigé par S. Pineau est disponible sur
http://steph.pineau.free.fr/php/index.php?LNK=EDIT avec un moteur de recherche multicritères pour vous guider dans votre choix.
- IDE complets
- Macintosh :
- Dos / windows 3x
- Windows NT / 9X /2000
Il nait presque un éditeur
par jour pour windows. Le but n'est pas de les lister tous.
- Unix
- Emacs et emacs win32 :
http://www.emacs.org/ : "plugins"
- vim et vim win32:http://www.vim.org/
2.7 Passage de variable(s) entre les scripts
[HS] La solution la plus courante et la plus simple consiste à
transmettre les variables dans l'URL sous la forme normalisée:
http://mon_url.fr/mon_beau_script.php3?variable1=valeur1&variable2=valeur&...&variableN=valeurN
Depuis la version 4.x de PHP, par défaut, les variables
$variable1, $variable2, ... $variableN ne SONT PLUS définies.
Il faut donc utiliser à la
place les tableaux $_GET[], $_POST[] ou depuis la version 4.0.6
$_REQUEST[].
Autrement dit, là oû avant en appelant : script.php?toto=1 il était
possible d'utiliser directement la variable $toto (qui valait 1) il
faut maintenant par exemple commencer par affecter $toto=$_REQUEST['toto'];
pour que $toto soit disponible. Noter les simples quotes autour de
'toto'.
Voir la documentation sur
http://fr2.php.net/manual/en/language.variables.external.php [en anglais]
ou
http://fr2.php.net/manual/fr/language.variables.external.php [en francais]
pour plus d'informations.
ATTENTION : vous devez vous préoccuper de la sécurité de votre programme, et donc
faire attention au contenu de ces variables.
Rappelons aussi l'emploi parfois judicieux d'urlencode ( ) et
de rawurlencode( ) ainsi que la préférence de la
méthode POST et non GET.
Si vous vous posez ce genre de
questions, il est probable que vous aurez aussi d'autres questions de
base sur le HTML et il est probable que créer quelques pages
statiques avant de vous intéresser à la création
de pages dynamiques serait plus logique, afin d'échelonner les
difficultés. N'hésitez pas à user et abuser de
la liste des ressources présente dans cette FAQ.
2.8 Passer des variables JavaScript à
PHP
Lire plus haut : HTTP : client serveur en mode asynchrone non
connecté
2.9 La différence entre include( ) et
require ( )
Remarque : include_once() et require_once(), introduits dans PHP4,
ont le même comportement. Ils garantissent de plus que le fichier inclus ne le sera qu'une fois et une seule,
ce qui facilite l'inclusion de fichiers définissant des fonctions (même si on peut très facilement se passer de
ces fonctions).
Manuel pour include ( )
http://fr2.php.net/manual/function.include.php [en anglais] ou
http://fr2.php.net/manual/fr/function.include.php [en français]
Manuel pour require ( ) http://fr2.php.net/manual/function.require.php
[en anglais] ou http://fr2.php.net/manual/fr/function.require.php [en français]
include( ) comme require( ) permettent
toutes les deux d'inclure un fichier dans un script php.
Une
application pratique courante est de définir des fonctions
dans un script qui sera appelé par include( ) ou require( )
pour rendre ces fonctions disponibles dans ce script.
En PHP 4.x
La seule différence enter les deux fonctions est leur comportement dans le cas où le fichier
à inclure est introuvable/inaccessible. include('fichier_inaccessible.toto'); produira un warning mais le script continuera.
require('fichier_inaccessible.toto'); stoppera l'exécution (comme s'il y avait un appel à exit() ou die()
qui est un synonyme d'exit()). (lire aussi ci-dessous la version PHP3 et son utilisation)
Par conséquent, en PHP4 et PHP5, sauf cas exceptionnel, vous devriez toujours utiliser require() ou require_once() et non plus include() et include_once().
En PHP 3.x
L'instruction
require ( ) est traitée avant l'exécution réelle
du script, par le préprocesseur PHP. Elle relève plus
de la macro que de la fonction. La fonction include( ) est appelée,
si nécessaire, au cours de l'exécution du programme.
Par exemple :
if($toto)
{
include("fic1.php3");
require("fic2.php3");
}
Dans ce code, le fichier fic2.php3 sera TOUJOURS inclus dans le script courant. En
revanche, fic1.php3 ne sera inclus QUE si le test sur $toto renvoie
TRUE.
Si pour une raison quelconque vous voulez inclure un
fichier juste après l'avoir généré
dynamiquement, vous êtes donc obligé de passer par
include ( );
Dans toutes les versions
Si vous tenez *vraiment* à faire des versions
différentes de votre site selon le navigateur, ceci peut vous
permettre de définir de deux manières différentes
la même fonction PHP, en adaptant ce qu'elle doit faire aux
spécificités d'IE ou NS ( sorte de couche
d'abstraction), ainsi le code du corps de votre site reste
indépendant de tout ça.
2.10 Les chemins pour include( ) et require
( )
Les deux fonctions ont le même comportement pour aller
chercher le fichier à inclure. Si on fait un
require("../titi.inc"); dans le fichier toto.php, alors,
le chemin de titi doit être relatif à toto.php. Dans
cet exemple, il se trouve un répertoire au dessus.
Attention
1 : chez la plupart des hébergeurs , php est configuré
de manière à interdire l'include de fichiers d'un
répertoire parent pour d'évidentes raisons de sécurité.
Attention 2 : il est plus que conseillé de nommer ses
fichier à inclure avec une extension .php ou .php3 car sinon,
n'importe qui connaissant le nom du fichier le lira en clair dans son
navigateur.
2.11 Du bon usage de la fonction header()
Il est important de comprendre le fonctionnement de la fonction header() avant
de l'utiliser à tout va. La fonction header() envoit vers le
navigateur une trame http ne contenant pas de données type html mais seulement,
comme son nom l'indique, des "headers" c'est à dire des entêtes techniques.
En particulier, elle peut donc être
utilisée pour annoncer que vont suivre des données de type binaire et donc être
utilisée pour proposer directement une fenêtre de téléchargement d'un fichier.
Un exemple à ce sujet est disponible dans cette FAQ (cf Techniques de développement,
L'envoi de fichiers vers le navigateur) .
Il est également possible d'utiliser header("Location:...")
pour rediriger l'internaute vers un autre site ou vers son propre site mais
en changeant de protocole pour passer en https/ssl. A noter que
header("Location:http://www.autresite.com"); est strictement équivalente
dans son résultat et le transit des données
à l'action d'une balise <META http-equiv="refresh" content="0; http://www.autresite.com"> en HTML pur :
on donne au navigateur l'instruction de
demander une autre page sans intervention de l'internaute. Il y a donc
transmission de données du serveur vers le navigateur, puis nouvelle requête
HTTP de la part du navigateur en direction du site http://www.autresite.com
(avec éventuellement requête DNS).
Remarque : il y a des différences entre les header http et les balises
meta mais le trajet de l'information est le même. Plus d'informations
sur : http://www.w3.org/QA/Tips/reback
Par conséquent, vous ne devriez pas utiliser header("Location:...script2.php") pour rediriger entre
deux scripts de votre site. Cela imposerait un aller-retour inutile entre le
serveur et le navigateur (traffic réseau inutile et dégradation des temps de
réponse de votre site proportionnels à la vitesse
de connexion de l'internaute). Il est bien plus rapide d'ajouter simplement dans
le code php les instructions : require("script2.php"); exit();
De plus, l'utilisation de header:Location ouvre souvent la faille de sécurité suivante :
- on reçoit les données sur check.php, qui les vérifie dans tous les sens
- si problème on redirige vers erreur.php ou generer_formulaire.php (jusqu'ici, c'est sous-optimal,
mais pas encore dangereux)
- si tout va bien, on appelle header:Location vers insert.php et là en revanche il est donc possible
d'appeler directement insert.php dans l'URL en lui passant n'importe quoi, les arguments ne seront jamais
vérifiés.
2.12 Des problèmes avec la fonction
header( )
Pour tout appel à la fonction header( ), il ne doit en
aucun cas y avoir un quelconque caractère retourné au
navigateur avant son appel.
En particulier, faire la chasse aux
espaces et aux retours à la ligne avant le tag d'ouverture
<?php ou après le tag de fermeture ?> des scripts php.
De même, des problèmes ont
été constatés lors de l'appel à une
fonction qui faisait un return; vide dont le code de retour n'était
pas traité dans la fonction appelante, un peu comme si la
valeur retournée était parasite.
Manuel :
http://fr2.php.net/manual/function.header.php [en anglais] ou
http://fr2.php.net/manual/fr/function.header.php [en français]
Un autre moyen de s'affranchir de la chasse aux espaces et aux retours
chariots oubliés est d'utiliser l'output buffering, qui consiste en
gros à mettre ob_start() en première ligne et ob_end_flush() en
dernière. Voir le manuel :
http://fr2.php.net/manual/en/ref.outcontrol.php
.
2.13 Remplacer les retours chariots dans une
chaîne
$chaine = ereg_replace("(\r|\n){1,2}", " ",$chaine);
2.14 Les expressions régulières
Sujet trop vaste pour être traité dans une FAQ de NG, et non réellement lié à PHP.
Des exemples sont présents dans cette FAQ.
Vous pouvez aussi consulter utilement les liens suivants :
http://www.linuxfocus.org/Francais/July1998/article53.html
http://www.phpbuilder.com/columns/dario19990616.php3
http://www.sitepoint.com/article/regular-expressions-php
http://www.zytrax.com/tech/web/regex.htm
ainsi que le chapitre Regexp de l'ouvrage PHP et MySQL en ligne de Jean Carfantan disponible sur phpindex.com : http://www.phpindex.com/download/regex.pdf
2.15 Variables dynamiques $var_$i =>$var_1,
$var_2 ...
Il est possible en PHP de gérer des variables dynamiques,
par exemple :
for ($n = 0; $n<4; $n++)
{
${"var_".$n}= "tutu".$n;
}
Cette
boucle génère 5 variables : $var_0 à $var_4, qui
contiennent le texte tutu0, tutu1...tutu4
2.16 Un @ devant la commande ?
On rencontre parfois des scripts de ce genre :
@mysql_connect(...
La présence du @ empêchera l'affichage d'une
éventuelle erreur.
http://fr2.php.net/manual/en/language.operators.errorcontrol.php[EN] ou http://fr2.php.net/manual/fr/language.operators.errorcontrol.php[FR]
ATTENTION : il vaut mieux GERER les erreurs que de les
IGNORER.
17 Mon code PHP s'affiche au lieu d'être éxécuté
Le plus probable est que vous avez nommé votre fichier avec une extension .html ou .htm et non .php3 ou .php,
c'est aussi simple que cela. Si le fichier a bien une extension .php3 ou .php,
alors votre serveur http n'est pas configuré correctement ou n'a pas été redémarré
pour prendre en compte les modifications.
NB : il est possible de forcer l'association des fichiers .html avec PHP, mais attention aux performances.
Ce genre de paramétrage n'a pas de raison d'être sauf dans des cas trè précis et
spécifiques.
Une autre erreur classique est d'ouvrir directement le fichier PHP dans le navigateur quand on travaille
sur la machine où se trouve le serveur http, ce qui se détecte aisément car l'URL est de la forme file:// et non http://
18 Les quotes : dois-je utiliser ' ou " ??
La règle absolue, et subjective, est la lisibilité du code. Les différences de performance sont suffisement
négligeables par rapport aux algorithmes à optimiser pour ne pas rentrer en ligne de compte.
Contenu de cette
section
3. La connexion à un sgbdr
Contenu de cette section
3.1 ...0 is not a valid resource ...
ou encore ...0 is not a valid mysql index on line...
La
requête SQL a échoué et vous n'avez pas pensé
qu'il faut toujours tester la valeur de retour d'une fonction aussi
cruciale pour le résultat attendu qu'une requête sur BD,
mysql_query( ) ici. Donc le premier appel au buffer de stockage du
résultat, par mysql_fetch_*( ), provoque une erreur.
Pour
trouver l'erreur dans votre requête SQL, affichez par un appel
à echo "";ou print( ); la requête passée
dans l'appel à mysql_query( ); et exécutez cette
requête en ligne de commande dans MySQL.
Pensez à ne pas mettre de ";" final dans la requête envoyée à Mysql.
Ceci donne donc schématiquement :
$dad=...; // le resultat de mysql_connect() voir une fonction pour ce faire dans cette FAQ.
$query="SELECT les colonnes FROM la table WHERE conditions SANS LA ; FINALE";
echo "DEBUG#$query#";
$res=mysql_query($query,$dad);
if($res==FALSE) exit("Erreur.");
while($row=mysql_fetch_XXXX($res))
{
// utiliser $row
}
3.2 [souvent HS] Problèmes de
connexion à MySQL
Manuel de MySQL (FR):
http://dev.mysql.com/doc/mysql/fr/index.html
Quelques messages d'erreurs rencontrés assez
souvent et ce qu'ils peuvent cacher :
Message d'erreur du
genre :
Fatal error : call to unsupported or undefined
function mysql_connect() in [fichier].php on line [XXX]
ATTENTION
: PHP4 possède un support natif de mysql, cette réponse
n'est applicable QUE à PHP3.
Vérifier que dans le
fichier php3.ini ou php.ini une ligne n'est pas encore commentée à
tort.
Par exemple dans ce cas, sous windows, dans la section
;Windows Extensions il faut enlever le ; devant
extension=php3_mysql.dll (mais donc laisser cette ligne commentée
avec PHP4)
Message d'erreur du genre :
... Can't
connect to mysql server on ...[HS]
Vérifier que le "démon"
mysqld (ou mysqld-shareware) a bien été lancé en
ligne de commande, par "c:\mysql\bin\mysqld.exe --standalone"
sous windows 9x, en tant que service sous Windows NT (c'est le plus
simple) et par "$MYSQL/bin/safe_mysqld &" sous unix (en
standard $MYSQL vaudra /usr/local mais ceci dépend de votre
installation).
Message d'erreur du genre :
...
Access Denied for user [toto]@localhost ... [HS]
Si votre script
tourne chez un hébergeur, contactez son support technique et
lisez sa documentation interne.
Si vous avez la main sur le
serveur MySQL, vérifiez les droits de connexion de ce [toto]
en vous connectant, en ligne de commande, à MySQL en tant que
user root, en faisant une fois connecté un select * from user
where user='[toto]'; et regarder tout particulièrement la
colonne Host.
Voir le manuel de mysql :
http://dev.mysql.com/doc/mysql/en/privilege-system.html
[en anglais] ou
http://dev.mysql.com/doc/mysql/fr/privilege-system.html
[en français] de MySQL pour plus d'informations.
3.3 Exemple de fonction de connexion à
MySQL
Cette fonction de connexion appelle une fonction fx_footer( ), que
vous devrez définir vous même, avec des arguments
qui vous conviennent, par exemple dans le cas où vous
disposez d'un menu de navigation paramétrable. Sinon, un
echo "</BODY></HTML>"; fera l'affaire.
La
terminologie DAD (Database Access Descriptor) est empruntée à
Oracle.
Remarque : De manière générale, il vaut mieux forcer les valeurs par défaut à des
valeurs que vous matrîsez.
function fx_std_connect( )
{
/* remplacer éventuellement localhost par le nom de serveur approprié.
Voir la doc de votre hébergeur. */
$l_dad=mysql_connect("localhost","votre_login","votre_password");
if ($l_dad == FALSE)
/*
NB1 : on peut faire appel à la fonction mysql_error() ou mysql_errno() pour obtenir le
message de retour de la base
NB2 : selon la configuration de PHP, utiliser eventuellement le caractere @ avant l'appel a mysql_connect
ou mysql_select_db pour supprimer les messagse d'erreur
*/
{
echo "Connexion impossible.\n";
require("std_footer.php");
fx_footer("parametre1","parametre2");
exit();
}
if(mysql_select_db("votre_base",$l_dad)!=TRUE)
{
echo "Database inaccessible.\n";
require("std_footer.php");
fx_footer("parametre3","parametre4");
exit();
}
return ($l_dad);
}
Pour chaque nouvelle connexion, appeler directement
$DAD=fx_std_connect( );
Il va de soi que cette fonction doit
être définie dans chaque script où elle est
appelée, le plus simple étant de faire un
require_once("std_connect.php"); où std_connect.php est
le fichier qui en contient sa définition.
Si le fait de mettre ainsi votre login et mot de passe en clair dans un
fichier vous effraie, lisez dans cette FAQ la section appropriée
: "La protection de mes mots de passe de connexion à une base".
3.4 La protection de mes mots de passe de
connexion à une base
Il existe de nombreuses méthodes permettant de sécuriser
les informations relatives à la connexion vers une base de
données. Nous allons en présenter ici quelques unes. En
premier lieu, précisons qu'il est pratique de placer ces
informations dans un fichier et/ou une fonction. Cette approche,
modulaire, permet de procéder à des modifications
ultérieures avec souplesse (changement du mot de passe d'accès
à la base, etc.).
Par exemple, dans le cas particulier
de MySQL, un fichier regroupant ces informations pourrait ressembler
à celui-ci :
$host="mon_host";
$user="mon_user";
$password="mon_password";
$acces_bd=mysql_connect($host, $user, $password);
**
Première méthode de protection Cas où
vous n'avez pas la maîtrise du serveur qui héberge vos
scripts
Nommer ce fichier en prenant soin de lui attribuer
l'extension .php3 ou .php pour PHP4. Par exemple, base.inc.php3. Par
ce simple fait, si un utilisateur mal intentionné tente
d'ouvrir ce fichier à l'aide d'un simple navigateur, ce
fichier sera de toutes facons "parsé" (interprété)
par PHP coté serveur. Et le navigateur ne renverra rien de
visible au client.
** Deuxième méthode de
protection Cas où vous avez la maîtrise du serveur
qui héberge vos scripts
Rien ne vous empèche de
placer le fichier contenant les informations de connexion à
votre base, en dehors de l'arborescence du serveur HTTP. C'est une
bonne approche. Un serveur HTTP dispose d'une racine en aval de
laquelle vont être placés et interprétés
vos scripts et vos pages. Mais en amont, non. Par exemple, sous
Apache, la racine (directive DocumentRoot de httpd.conf) est souvent
/usr/local/apache/htdocs. Les pages et autres scripts se trouvant en
aval de cette racine sont potentiellement visible depuis un
navigateur. Il n'en va pas de même de ceux qui se trouvent en
amont. Vous pouvez donc judicieusement placer votre fichier sous
/usr/local/etc par exemple.
Une autre technique consiste à
récupérer le login et password depuis des variables
shell unix par un getenv();
** Troisième méthode
de protection Cas où vous disposez des droits
d'administration de votre base
Une méthode trop souvent
ignorée consiste tout simplement à paramétrer
finement les droits d'accès à votre base. Notamment
afin de n'autoriser des connexions que depuis la machine locale
(localhost). De ce fait, même si un utilisateur mal intentionné
dispose des informations de connexion (et dans le cas où il ne
dispose pas d'accès sur la machine afin d'y déposer des
scripts, bien évidement), il ne pourra pas accéder à
la base. Reportez vous au manuel du sgbd que vous utilisez.
**
Les autres méthodes Ajoutons qu'il est aussi possible
de bricoler les fichiers de configuration des serveurs HTTP (type
Apache) afin de demander au serveur de "parser" les
fichiers .inc ou encore de jouer avec les droits d'accès à
certains répertoires ou fichiers (par le biais des fichiers
.htaccess par exemple), y compris dans des sous répertoires si
l'hébergeur interdit de "remonter" dans
l'arborescence.
N'oublions pas qu'il est plus probable que
votre mot de passe soit tout simplement "sniffé"
quand il passera en clair avec votre clickdrome (tm) favori
d'administration de base...
Contenu de cette
section
4. Techniques de développement
Contenu de cette section
4.1 ...parse error on line... Undefined index... Undefined constant...
parse error
parse error on line 55 : une erreur de parsing (en français
dans le texte) est une erreur de syntaxe php.
Il est important de comprendre que c'est l'équivalent d'une erreur de compilation
pour un langage compilé. Il est donc futile d'essayer d'écrire un gestionnaire d'erreurs
qui trappe les parse errors, ça n'a tout simplement pas de sens (sauf si vous écrivez un
moteur qui accepte du PHP en entrée).
Une erreur déclarée
sur la ligne N est très souvent causée sur la ligne N-1
sur cet exemple, la ligne 54.
L'erreur la plus courante est un
oubli de ';' en fin de ligne...
Un autre grand classique est
l'oubli de '\' devant des double-quotes ou l'oubli des double-quotes
finales dans une chaîne de caractères.
On rencontre
aussi une "parse error" en fin de fichier quand on oublie
une accolade fermante } dans un bloc conditionnel. Typiquement, si
votre fichier fait 204 lignes et que vous avez une "parse error"
sur la 205eme, c'est un très probablement un problème
d'accolades.
Undefined index
Selon le niveau d'erreur réglé dans php.ini (ou autrement), PHP va signaler
les accès aux variables non définies et en particulier les tableaux.
Si dans un script vous accédez à $tableau['toto'] mais que jamais cet indice du
tableau n'a été initialié, vous aurez cette erreur.
Vous devez alors :
- ou vous assurer que la variable sera toujours initialisée
- ou utiliser la fonction isset( )
4.2 Le multitasking / exécutions
parallèles (UNIX)
Si vous désirez lancer des scripts en parallèle
et/ou en asynchrone (on les lance et on les oublie, on continue le
script courant sans attendre qu'ils se terminent) vous pouvez
utiliser les fonctions PHP exec(), passthru(), ou system().
Par
exemple : exec(" nohup toto.sh >mon_log.txt &");
En
revanche, il faudra analyser le résultat en disséquant
("parser") le fichier de log : ouvrir ce fichier avec
fopen(); puis le lire ligne par ligne en cherchant des erreurs
éventuelles, etc...
4.3 Recherches par mots-clefs dans une base
de données
Il n'est pas rare de devoir effectuer des recherches dans une
basesur des données partielles, comme par exemple un mot-clef.
De manière générale, deux principes peuvent
être mis en oeuvre :
- gardez une table spécifique
pour la recherche, qui contiendra uniquement les mots-clefs en
majuscules et sans accents.
- si le sgbdr le supporte (mysql par
exemple) utilisez plutôt les regexp DANS la requête SQL
au lieu de faire du "WHERE machin LIKE '%toto%'".
http://www.mysql.com/doc/R/e/Regexp.html
4.4 Lancer des commandes à intervalles
réguliers ("crontab")
Commencez avant tout par vérifier si votre script doit être
absolument lancé à une heure précise en rapport
direct avec le temps newtonien. Ceci est en fait assez rare, et est
en général lié à des traitements assez
longs à exécuter de nuit.
Dans beaucoup de cas,
vous pourrez vous passer de crontab. Considérons par exemple
la purge de données obsolètes. "Tous les jours à
minuit" est une approche, mais en fait, il suffit de purger
avant la prise en compte ou l'affichage de ces données. Il
suffit donc d'appeller un script de purge avant le traitement. On
peut ensuite par exemple utiliser un fichier de configuration sur le
serveur (un peu comme un cookie) ou tester l'heure courante par
rapport à une plage horaire pour éviter de lancer la
purge à chaque appel.
Dans certains cas, néanmoins,
cette méthode n'est pas applicable. L'idéal est bien
sûr alors d'avoir accès à une crontab.
Sinon,
on peut faire appel à des services de sites qui appelleront
votre script à l'heure voulue comme par exemple:
http://www.witbe.net/
ou http://www.webcron.org/
(gratuit)
Il est également parfois possible de faire
un "daemon" en PHP, grâce à une boucle infinie
testant la présence d'un fichier par exemple, mais attention
aux obstacles suivants :
- Dans la plupart des cas le temps
maximum d'exécution d'un script est limité, en
particulier par un paramètre de php.ini. Ce temps semble être
du temps CPU, mais ceci est à confirmer, en particulier la
gestion de ce paramètre est os-dependant.
- Attention à
ne pas oublier de faire un appel à la fonction clearstatcache(
) si vous utilisez effectivement un test sur la présence d'un
fichier pour arrêter votre démon ou c'est la boucle
infine garantie.
4.5 Vérifier la présence d'un
enregistrement avant de le mettre à jour
(La stratégie d'update / insert, limite hors sujet )
Pour
vérifier la présence d'un enregistrement avant de le
mettre à jour on peut procéder de la manière
suivante :
1.Faire un select dans la table appropriée.
2.Tester le retour du nombre de rangs, par exemple grâce à
mysql_num_rows ()
3.Si l'enregistrement n'existe pas, alors on
fait un insert.
Sinon, on fait un update.
Une méthode
plus rapide est la suivante :
Lancer l'update. Si le nombre de
rangs mis à jour est égal à zéro, c'est
que le rang n'existait pas dans la base.
Il n'y a plus qu'à
l'insérer.
Comparaison du code des deux méthodes
:
$result=mysql_query("SELECT * FROM ma_table WHERE ma_clef='$MA_VAR'");
$nbre_rangs=mysql_num_rows( $result);
if ($nbre_rangs == 1)
{
$modif=mysql_query("UPDATE ma_table SET colonne=colonne+1 WHERE ma_clef='$MA_VAR'");
if (!$modif)
{ return(FALSE); }
}
else
{
$modif=mysql_query("INSERT INTO ma_table VALUES ('$MA_VAR',0)");
if (!$modif)
{ return(FALSE); }
}
Deuxième méthode :
/* $DAD = Database Access Descriptor, retour de mysql_connect() */
if (! mysql_query("UPDATE ma_table SET colonne=colonne+1 WHERE ma_clef='$MA_VAR'"),$DAD)
{
if(mysql_affected_rows($DAD)==0)
{ mysql_query("INSERT INTO ma_table VALUES ( '$MA_VAR', 0)",$DAD); }
}
Il est à noter que le code de la deuxième
méthode, beaucoup plus compact et plus performant, est
néanmoins plus permissif car il n'intègre pas de
gestion des erreurs.
NB : dans le cas de MySQL intéressez
vous à la commande REPLACE.
4.6 Gérer plusieurs langues sur un
site
Voir le travail de Nicolas Hoizey : phpLang sur
http://www.phpHeaven.net/
Par ailleurs, il est possible de définir la même
variable PHP, avec une valeur différente selon la langue
simplement en se servant de fichiers à inclure.
Soit par
exemple une gestion de trois langues: allemand (DE), anglais (EN), et
français (FR). Le code de toute page PHP commencera par le
code suivant :
$l_langue=fx_filtrer($i_langue);
/* On
filtre toute variable arrivant du monde extérieur */
switch
($l_langue)
{
/* Profitons de la capacité de PHP à
accepter des chaînes
de caractères dans les switch(
) */
case "FR" : include("FR_mesg.php");
break;
case "EN" : include("EN_mesg.php");
break;
case "DE" : include("DE_mesg.php");
break;
default : echo "Langue non reconnue
";
fx_footer("parametres divers");
exit();
/*
N'oublions pas le cas par défaut qui permet de traiter TOUTES
les erreurs d'un seul coup */
}
Les fichiers contiendront
une définition différente des mêmes variables /
constantes :
Dans FR_mesg.php : define(msg1,"Bonjour");
Dans EN_mesg.php : define(msg1,"Hello");
Dans
DE_mesg.php : define(msg1,"Gunten Tag");
Dans le code
du script, il suffira d'afficher la constante msg1 sans réfléchir
: la bonne langue sera automatiquement sélectionnée.
Il est bien entendu aussi possible de stocker des messages dans
une table d'une base de données qui aura trois colonnes :
l'identifiant du message (msg1,...msgn), la
langue, et le texte,
la clef primaire étant bien sûr le couple (identifiant,
langue).
4.7 Connaître la version du navigateur
et la résolution de l'écran
Remarque : il n'est pas particulièrement conseillé
de faire des versions différentes d'un site selon la
configuration du client qui va le voir (version du navigateur,
résolution de l'écran...), en particulier pour la
maintenance du code. Pour plus d'informations sur ce débat qui
n'a rien à voir avec PHP, reportez vous au newsgroup
fr.comp.infosystemes.www.auteurs ou fciwa et en particulier à
ses archives sur http://groups.google.com/
La variable globale HTTP_USER_AGENT contient la version du
navigateur ayant demandé la page (ou celle qu'il a bien voulu
donner par exemple dans le cas d'un "aspirateur").
Des multitudes de scripts tous aussi mal écris les uns que les autres triturent cette variable
dans tous les sens. Intéressez vous plutôt à la fonction PHP get_browser () :
http://fr2.php.net/manual/en/function.get-browser.php
La résolution de l'écran n'est pas transmise au serveur
par le navigateur. Si vous souhaitez vraiment vous en servir,
utilisez JavaScript.
4.8 Imprimer
Non, on ne peut pas. Le serveur sur lequel tourne PHP n'a aucune
connaissance des millions d'imprimantes connectées aux
millions de PC/mac/autres de ceux qui regardent vos pages, c'est
aussi simple que ça.
Si pour une raison quelconque, le
bouton "imprimer" du navigateur ne vous convient pas, c'est
en JS qu'il faudra gérer vos traitement spécifiques,
côté client.
4.9 Alterner les couleurs dans un tableau
Pour autant que cela ait un réel intérêt
graphique (en tous cas, c'est à la mode), il est très
simple d'alterner les couleurs du fond d'un tableau.
Un exemple :
while($row =mysql_fetch_row($result_buffer) )
{
if($bg_color=="red"){$bg_color="green"}else{$bg_color="red"}
print "<TR><TD BGCOLOR=$bg_color>$row[1]</TD></TR>";
}
Remarque : pour les navigateurs qui gèrent correctement
les CSS, on peut utiliser la méthode suivante :
<style type="text/css" media="print">
td { border-bottom : thin solid Gray;}
</style>
4.10 L'upload de fichiers
A voir dans la doc :
http://fr2.php.net/manual/features.file-upload.php
[en anglais] ou http://fr2.php.net/manual/fr/features.file-upload.php
[en français]
Prérequis dans le formulaire :
-
le formulaire doit être en encodage (enctype) multipart/form-data et en méthode POST.
<form action="script.php" enctype="multipart/form-data" method="POST">
- un champ (en général caché) nommé
MAX_FILE_SIZE dont la valeur sera la taille maximale
acceptée
pour les fichiers, exprimée en octets. Ce champ est
facultatif.
<input type="hidden" name="MAX_FILE_SIZE" value="1000">
- un champ de type "file", le nom n'importe pas, appelé
LeFichier pour la suite.
<input type="file" name="LeFichier" >
Gestion dans le script :
Le script recevant le formulaire va créer 5 variables pour chaque fichier
chargé :
$_FILES['LeFichier']['tmp_name'] : l'emplacement temporaire du fichier sur le serveur
$_FILES['LeFichier']['name'] : le nom du fichier initial dans l'ordinateur client
$_FILES['LeFichier']['size'] : la taille du fichier exprimée en octets
$_FILES['LeFichier']['type'] : le type MIME du fichier (à condition que le navigateur l'ait renseigné!)
$_FILES['LeFichier']['error'] : le code retour de l'upload (php version>=4.2).
Ce code retour peut avoir les valeurs suivantes :
0 : tout va bien, fichier uploadé
1 : la taille du fichier dépassait la limite fixée dans php.ini
2 : la taille dépassait la limite fixée par le formulaire
3 : le chargement du fichier a été interrompu
4: le fichier n'a pas été chargé
On peut aussi simplement tester is_uploaded_file($_FILES['LeFichier']['tmp_name'])) qui renvoit FALSE si le
fichier n'a pas pu être uploadé.
Reste donc simplement à déplacer le fichier temporaire dans un autre
répertoire, par exemple : $DOCUMENT_ROOT."/upfiles/"
Ce répertoire cible doit être accessible en écriture. On peut le vérifier
avec is_writeable($DOCUMENT_ROOT."/upfiles/")
http://fr2.php.net/manual/en/function.is-writeable.php
[en anglais] ou
http://fr2.php.net/manual/fr/function.is-writeable.php
[en français]
Ensuite donc, on déplace : la
fonction copy ( ) est utilisablee car rename( ) ne fonctionne pas
toujours en multivolumes :
if (!copy($_FILES['LeFichier']['tmp_name'],
$DOCUMENT_ROOT."/upfiles/".$_FILES['LeFichier']['name']))
Mais il vaut mieux encore appeler move_uploaded_file() (PHP 4 >= 4.0.3).
if(!move_uploaded_file($_FILES['LeFichier']['tmp_name'],
$DOCUMENT_ROOT.'/upfiles/'.$_FILES['LeFichier']['name']))
print 'erreur à la copie du fichier '.$_FILES['LeFichier']['name'];
http://fr2.php.net/manual/function.move-uploaded-file.php
http://fr2.php.net/manual/fr/function.move-uploaded-file.php
Remarques:
Si vous avez des problèmes à uploader les fichiers, vérifiez les
paramètres suivants du fichier php.ini :
file_uploads=1
upload_tmp_dir= un répertoire temporaire auquel l'utilisateur php a accès en
écriture (sous windows, c:/windows/temp semble un bon candidat)
upload_max_filesize=taille maxi d'un fichier uploadé
post_max_size=taille maxi des données envoyées par un formulaire
(y compris les fichiers uploadés)
Sachez aussi que cette méthode d'upload par le protocole http n'est ni fiable ni adaptée aux
gros fichiers; s'ils font plus de 2Mo envisagez plutôt un transfert par ftp.
Il est inutile de stocker des fichiers complets dans
une base de données, leur chemin suffit. Une exception
néanmoins si le but est de faire du PHP dynamique avec eval()
mais ce seront des "petits" fichiers.
En
particulier, il est rigoureusement inutile de stocker des fichiers
binaires comme des images dans une base de données. Si
vous le souhaitez vraiment (on ne peut pas vous empêcher...),
pensez sous Oracle à utiliserle type BFILE, qui n'est pas
stocké dans le tablespace.
Pour des raisons de sécurité, vérifiez toujours l'extension des fichiers
uploadés pour bloquer ceux qui seraient exécutables (extensions '.php',
'.php3', '.cgi', etc.), de préférence avec une liste d'extension explicitement autorisées,
ou bien stockez tous vos fichiers uploadés dans un
répertoire rendu inaccessible par le serveur HTTP (sous Apache .htaccess par exemple).
L'upload de fichiers fonctionne bizarement chez l'hébergeur Free. Il semble
que le script appelé doive avoir l'extension php3.
4.11 L'envoi de fichiers vers le navigateur
Pour envoyer un fichier vers le navigateur du client par un simple
lien http, il est possible d'utiliser la fonction header() (avec les
précautions rappelées dans cette FAQ) :
header("Content-disposition: attachment;
filename=nom_fichier.txt");
Contenu de cette
section
5. Les mails et les forums NNTP
Contenu de cette section
5.1 Le mail chez free.fr
Oui, il est possible d'envoyer des mails depuis php chez free.fr.
http://www.free.fr/assistance/946-acces-libre-php-fonction-email.html
Remarque : 'Protomail' de Samuel Kabak n'est plus maintenu. Vous le trouverez néanmoins en faisant une recherche
sur votre moteur favori.
5.2 Envoi d'un mail.
Utilisez ou disséquez la très bonne classe de
gestion de Léo West, disponible sur
http://lwest.free.fr/doc/php/lib/Mail/
Documentation en français sur
http://lwest.free.fr/doc/php/lib/index.php3?page=mail&lang=fr
5.3 Tester la validité d'une adresse
email
(merci à O.Miakinen pour la nouvelle rédaction de ce paragraphe)
Définition : une adresse électronique est valide
si elle est syntaxiquement correcte
et si elle est sur un nom de domaine qui existe
et si le compte existe dans ce domaine
et si l'adresse appartient bien à la personne qui vous l'a
donnée.
Cette dernière vérification est indispensable pour éviter
d'inscrire quelqu'un contre son gré. La meilleure façon de
s'en assurer -- sinon la seule -- consiste à envoyer
à cette adresse une demande de confirmation, accompagnée d'un
identifiant unique généré aléatoirement. Si l'adresse est valide
et que son propriétaire est bien celui qui a donné cette adresse
sur votre site, il renverra la confirmation et vous pourrez
valider sa demande ; sinon, vous annulerez cette demande après
un certain délai (48 heures par exemple).
Toute autre sorte de validation sera (au mieux)
incomplète ; au pire elle refusera des adresses valides.
Oubliez donc toute tentative de vérification basée sur l'interrogation
d'enregistrements DNS de type MX, tentative qui sera aussi coûteuse
qu'inefficace.
En réalité, il faut appliquer à une adresse email exactement
le même genre de contrôle qu'à tout ce qui vient de l'extérieur, pour
éviter qu'elle serve de point d'attaque, par exemple à un spammeur.
Ainsi, il faut au moins en exclure les sauts de ligne et les chevrons
(< et >), de même que tout ce qui pourrait provoquer un effet de bord
dans vos programmes.
Une règle élémentaire dictant de lister les caractères autorisés
plutôt que les caractères interdits, voici un code qui reconnaît
les syntaxes simples (c'est-à-dire sans caractères d'échappement
"" ou \) :
$ltext = '[A-Za-z0-9!#$%&\'*+/=?^_`{|}~-]+';
$rtext = '[A-Za-z0-9-]+';
$pattern = ":^$ltext(\.$ltext)*@$rtext(\.$rtext)+$:";
if (preg_match($pattern, $email)) { ... }
En cherchant un peu sur Internet, vous pouvez trouver des
expressions régulières gigantesques gérant la syntaxe complète
décrite dans les RFC 822 et 2822 (avec ou sans les commentaires),
mais avant d'utiliser ce genre de syntaxe posez-vous la question
de savoir si vous voulez vraiment accepter des adresses de la forme
"@"@example.com ou
"@"(si ! si !)@example.(ici aussi)com.
Si au contraire vous préférez une expression plus simple puisque de
toute manière la vraie vérification se fera par un message de confirmation,
voilà pour vous satisfaire sans frustrer vos visiteurs honnêtes :
$pattern = ':^[.A-Za-z0-9!#$%&\'*+/=?^_`{|}~-]+@[.A-Za-z0-9-]+$:';
if (preg_match($pattern, $email)) { ... }
Enfin, si vous êtes vraiment parano, vous pouvez restreindre
le répertoire utilisé pour la partie gauche de l'adresse,
par exemple pour en exclure les caractères guillemet simple ('),
pourcent (%) et esperluette (&),
mais par pitié n'en excluez-pas le caractère plus (+) :
if (preg_match('/^[.A-Za-z0-9+_-]+@[.A-Za-z0-9-]+$/', $email)) { ... }
5.4 Forums usenet
1) Il est possible d'utiliser soit les sockets, soit les fonctions
IMAP pour accèder en lecture / écriture à un
serveur de news :
- L'article d'Armel Fauveau (en VF) traitant de la gestion des sockets avec php en lien avec un serveur NNTP :
http://www.phpheaven.net/articles/php_et_les_sockets_article9.html
- pour imap, le manuel :
http://fr2.php.net/manual/fr/ref.imap.php
- Sans oublier la RFC 977 traitant du NNTP :
http://www.ietf.org/rfc/rfc0977.txt?number=977
2) classes NNTP disponibles en php :
http://www.vhconsultants.com/nnrp/nnrp.htm
avec un tuto de présentation disponible ici :
http://www.phpteam.net/affiche.php?quoi=socket1
http://phpclasses.upperdesign.com/browse.html/package/157
Le projet PEAR : http://cvs.php.net/cvs.php/pear/Net_NNTP
3) Des projet de client NNTP via php :
http://florian-amrhein.de/newsportal/index-english.php3
http://sourceforge.net/projects/phnntp/
Contenu de cette section
6. Les outils déjà prêts
Contenu de cette section
6.1 Code d'un forum ou BBS en PHP
ATTENTION. Une extrême vigilance sur les mises à jour de sécurité doit être de mise
si vous utilisez de tels forums.
Il existe des projets "tout prêts" et gratuits.
Par exemple :
- phorum http://phorum.org/
- agora http://w-agora.net
Si vous préférez faire le votre, un très
bon exercice, inspirez vous de leur code (ce qui est du "hacking"
au bon sens du terme).
Si vous possédez le livre de Leon
Atkinson (cf en bas pour toutes ses références), voir
le chapitre 16 pour un exemple.
6.2 Code d'un caddie virtuel en PHP
Intéressez vous au projet en Open Source d'Alexandre Trusch
: http://www.w3-concept.net/
Et la démo de ce projet : http://demo.w3-concept.net/.
On peut également citer http://www.oscommerce.org/ sur lequel des versions en français sont disponibles sous forme de packages complémentaires.
6.3 Code d'un "chat" en PHP
Voir le travail de Nicolas Hoizey : phpMyChat sur
http://www.phpHeaven.net/
6.4 PHP-NUKE
En cas de problème avec php-nuke, merci de commencer par
consulter les ressources en ligne disponibles avant de poster sur
fclphp.
Site officiel : http://www.phpnuke.org
Liste de diffusion (en français) :
http://fr.groups.yahoo.com/group/php-nuke/
Alternatives diverses :
http://www.phpscripts-fr.net/?page=scripts&cat=Portails
6.5 Webmail
Une interface de consultation de mails en PHP :
SquirrelMail : http://www.squirrelmail.org/
IMP http://www.horde.org/imp/
Attention, cette application nécessite une foultitude de dépendances, en particulier sur le
"framework" horde et sur pear.
6.6 Spip (CMS)
SPIP : http://www.spip.net/
6.7 Typo3 (CMS)
Typo3 : http://www.typo3.org/
6.8 W-agora (CMS)
W-agora : http://www.w-agora.net/
6.9 Administration SGBDR
Quelques outils de gestion de SGBD en PHP :
Mysql : http://www.phpmyadmin.net/
Postgresql : http://phppgadmin.sourceforge.net/
Oracle : http://phporacleadmin.org/
Contenu de cette section
7. Gérer les sessions utilisateur
Contenu de cette section
7.1 Coder votre propre gestion de session
Cette méthode, la seule possible sous PHP3, reste la plus
souple et la plus fiable en ce qui concerne la capacité à
maintenir le code. On utilise en général une table dans
un SGBDR, contenant :
- un identifiant de session
- une
colonne de type date, mise à jour à chaque demande de
page, permettant aussi de faire expirer la session
- autant de
colonnes que l'on veut associer de données à la session
(dépendant de votre application)
L'identifiant de
session est transmis dans les liens et les formulaires. A toute
nouvelle connexion, on purge toutes les sessions inactives depuis
plus de N minutes, puis on vérifie si la session courante est
encore active.
Un générateur de session renvoie
suffisament de caractère "aléatoirement"
qu'il est impossible en termes de probabilités quepndant les N
minutes de connexion, le même identifiant soit généré
deux fois.
Deux grandes méthodes sont utilisées
pour coder un générateur d'identifiants. La première
consiste à se donner une liste de caractères autorisés
et à "piocher" aléatoirement dans cette liste
le nombre de fois voulu avec la fonction random(). La seconde repose
sur le système d'exploitation et des "bidouilles"
plus ou moins personnelles à chaque développeur,
faisant appel à des concaténations de l'heure système
et du PID du process courant par exemple.
Il est à
noter que ce type de sessions peut être historisé dans
une aute table, associée à un login/password par
exemple, ce qui rend l'utilisation de cookies totalement inutile et
perfidement, obligatoire pour l'internaute qui ne peut pas savoir ce
qu'on stocke sur le serveur, mais peut effacer ou refuser les
biscuits.
7.2 Utiliser l'excellente PHPLib
Ressources :
Site officiel de la PHPLib
https://sourceforge.net/projects/phplib/
NewsGroup dedié à la PHPLib
news://news.netimages.com/php3.phplib
Archives de la liste PHPLib du site PHPBuilder
http://www.geocrawler.com/lists/4/Web/195/0/
7.3 Le support natif des sessions de php4 & php5
A lire : http://fr2.php.net/manual/en/ref.session.php
ou en français http://fr2.php.net/manual/fr/ref.session.php
A noter : il est très tentant de faire n'importe quoi et
de stocker n'importe quoi dans des sessions avec php4. En
particulier, on ne peut PAS stocker un identifiant de connexion à
une base de données (par exemple le retour de mysl_connect)
dans un identifiant session.
Les sessions en PHP4 devraient être
réservées à des développeurs ayant un
minimum d'expérience et de compréhension des mécanismes
impliqués.
7.4 Comptabiliser le nombre courant de
personnes "connectées" sur le site
Disposant d'un identifiant unique par session, vous pouvez stocker
ces identifiants dans une table d'un SGBD, avec une colonne de
fonctionnalité "timestamp" qui permettra de savoir
quand l'enregistrement a eu lieu (mis systématiquement à
l'heure système). Vous pouvez alors sélectionner toutes
les sessions différentes "actives" dans, mettons,
les 3 dernières minutes : souvenons nous que HTTP sur TCP/IP
est un protocole utilisé en mode non connecté, il n'y a
personne qui soit connecté (au sens ouverture de session avec
authentification et fermeture explicite de session) à votre
serveur en regardant vos pages.
Vous pouvez aussi vous servir de
telles tables pour "suivre à la trace" les visteurs
par leur identifiant. Notez que l'adresse IP de votre visiteur n'est
a priori pas un identifiant fiable.
Remarque : si vous ne stockez
qu'un identifiant qui n'a aucun lien direct avec l'internaute que
vous "pistez", vous n'êtes en rien en contradiction
avec la CNIL. Le stockage d'IP, bien que techniquement délirant,
est plus sujet à caution.
7.5 Suivre ses visiteurs sur son site /
l'adresse IP de vos visiteurs
La solution la plus simple consiste à utiliser des
identifiants de session transmis d'une page à l'autre.
Les
autres solutions côté serveur (à l'exclusion,
donc, des cookies qui sont côté client) mettent en jeu
plusieurs variables PHP :
Dans le cas où il n'y a pas de
proxy(s) entre le client et le script php, $REMOTE_ADDR (ou
$_SERVER['REMOTE_ADDR'] ) est l'adresse
IP du client.
Dans le cas où il y a un (au moins) proxy,
les variables $HTTP_X_COMING_FROM (ou $_SERVER['HTTP_X_COMING_FROM']) et $HTTP_VIA (ou $_SERVER['HTTP_VIA'])
sont positionnées.
Attention donc, il n'est pas fiable d'utiliser
$REMOTE_ADDR comme identifiant.
Si le problème
vous intéresse, consultez la fonction GetIdentifier de Marc
Meurrens : http://www.cgsa.net/php/identifierShow.php
7.6 Mot de passe d'accès à un
répertoire
La quasi totalité des hébergeurs proposent une
interface graphique permettant de protéger l'accès à
un répertoire par un couple (login / mot de passe).
[HS]
Chez free.fr : http://http://faq.free.fr/accesgratuit/Administration_du_compte_et_services/Pages_Persos/Personnaliser_sa_page_perso/Comment_gerer_les_restrictions_d_acces
Dans le cas où il vous faudrait faire ceci "à
la main", une réponse sera rédigée en cas
de demande. Il suffit en gros de faire un "man htpasswd"
Ceci est à différencier d'une gestion
d'identification par login/passwd stockés dans une base de
données.
Contenu de cette
section
8. L'affichage de résultats de requêtes
par tranches
Contenu de cette section
8.1 Présentation du problème
Lorsqu'une requête SQL renvoie un grand nombre
d'enregistrements, on choisit souvent de n'afficher qu'un
sous-ensemble de ceux-ci et de proposer à l'utilisateur de
naviguer entre plusieurs pages de réponses (à la façon
des moteurs de recherche).
Pour cela, plusieurs solutions
sont possibles pour afficher les réponse $deb à $fin
(deux variables passées en paramètre dans l'URL). Nous
en présentons ici trois.
8.2 Faire une série de requêtes
SQL classiques et traiter en retour
Avantages :
Compatible avec toute les bases.
On peut
connaitre facilement le nombre total de réponses avec
mysql_num_rows()
Inconvénient :
cette méthode
est sous-optimale (!) en terme d'accès au sgbd et en
post-traitement, et est présentée pour la forme.
$res
= mysql_query("select nom, prenom from personne where age=30");
/* Boucler sur les résultats, en filtrant à
l'affichage : */
$i = 0;
while ($a = mysql_fetch_row($res))
{
if (($i >= $deb) && ($i <= $fin))
afficher_rang($a);
$i++;
}
8.3 Utiliser la clause LIMIT du select de
MySql
Avantage :
Utilisation optimale de MySql (et tout autre base
acceptant un mécanisme semblable)
Inconvénients :
Non applicable à la plupart des sgbdr (qui n'acceptent pas
cette notion de LIMIT)
On ne connait plus le nombre total de
réponses. Pour l'obtenir il faut effectuer une requête
supplémentaire lors avant la première tranche à
afficher : select count(*) from personne where age=30;
$query
= "select nom, prenom from personne where age=30 LIMIT $deb
,$fin ";
$res = mysql_query($query);
while ($a =
mysql_fetch_row($res))
affiche_row($a);
/* Lien avec $deb
et $fin2 en paramètre pour la page suivante */
$fin2 =
$fin-$deb +1;
$deb=$fin2;
8.4 Utiliser une table tampon
Avantages :
Totalement compatible / portable quel que soit le
sgbdr utilisé.
Compromis correct en utilisation des
ressources.
Inconvénients :
Nécessite une table
supplémentaire et un identifiant requête (ou session).
Remarque : la gestion des identifiants session est disponible
dans cette FAQ.
Ci-dessous, les grandes lignes de la méthode.
Un document plus détaillé est disponible donnant un
exemple de moteur de recherche affichant ses résultats page
par page sur http://johng.free.fr/requetes_tranches.html
1 - Créer une table fille, qui contient tout les
champs de la table mère qu'on veut rendre disponible à
la requête + 3 autres champs:
- une colonne id_session,
contenant l'id de session du visiteur qui permettra d'identifier le
résultat de la requête du visiteur, clef primaire de la
table avec l'ordre_session.
- une colonne ordre_session qui sera
incrémentée par chaque enregistrement d'une ligne de la
requête sur la table mère.
- une colonne
temp_session de type timestamp qui permettra de connaitre la date de
création des lignes de la requête pour les purger le
moment venu.
2.1 - On fait la requête sur la table
mère. Avec le résultat on l'insère ligne par
ligne dans la table fille, en n'oubliant pas de créer pour
chaque ligne un champ
ordre-session incrémenté de
1, et deux champs id_session et temp_session identiques pour toutes
les lignes de cette requête. On peut ici limiter le nombre
maximum
d'enregistrements à présenter. On dispose
alors du nombre total de lignes à afficher par tranches,
$nombre_lignes.
2.2 - On purge la table des enregistrements
dont le temp_session >= 20 minutes. (par exemple).
3 - On
crée une variable borne_inferieure = 1. On crée ensuite
une variable $borne_superieure = $borne_inferieure + $nombre_lignes;
En boucle pour chaque tranche :
4 - On fait une requête
du style:
SELECT * FROM table_fille WHERE
id_session='$id_visiteur'
AND ordre_session >
$borne_inferieure AND ordre_session < $borne_superieure
ORDER
BY ordre_session;
5 - On incrémente $borne_inferieure
= $borne_superieure + 1; et $borne_superieure += $nombre_lignes;
(ou
$borne_superieur=$nombre_lignes; si dépassement).
6 -
On crée un lien contenant $id_session du
visiteur,$borne_inferieure, $borne_superieure et $nombre_lignes.
Retour acte - 5.
(sauf si $borne_inférieure
>$nombre_lignes car dernière page)
Contenu de cette
section
9. Ressources PHP
Contenu de cette section
9.1 Manuels php
Attention, les traductions en français ne sont parfois pas à jour. En cas
de doute, référez-vous toujours à la version en anglais.
http://fr2.php.net et
http://fr2.php.net/docs.php
(anglais et français) dont la référence rapide :
http://fr2.php.net/quickref.php
Accès direct en français : http://fr2.php.net/manual/fr/
9.2 Ouvrages "papier"
NB : cette FAQ n'a pas pour finalité de tenir le rythme imposé par les éditeurs qui sortent un
nouvel ouvrage tous les mois ou presque. Il s'agit là d'exemples.
Pratique de PHP-Mysql P. Rigaux Editions O'Reilly
A noter que ce livre a été rédigé en français
et bien qu'il soit publié chez O'Reilly, n'a donc aucune horreurs de traduction.
Programmation web avec PHP (quatre co auteurs)
Editions
Eyrolles. 360 pages. http://clauer.free.fr/livrephp.php3
Programmation en PHP par Leon Atkinson
Editions Campus
Press. 450 pages, environ 200F.
Remarque : la première
édition comporte de nombreuses erreurs de traduction. Une
deuxième édition relue par Marc Meurrens est
disponible. Un réédition a eut lieu récemment (2004)
Professionnal PHP programming(cinq co auteurs)
Editions
Wrox. 900 pages, environ 360 F.
Disponible traduit chez Eyrolles.
Pages Web dynamiques avec ASP-PHP-SQL de Jean-Marc
Herellier et Philippe Mérigod.
Editions Campus Press.
9.3 Archives du NG fr.comp.lang.php
Les archives de phpindex http://www.phpindex.com/ng/
Dispose aussi des archives de fcas et fciwa
Google :
http://groups.google.com/
9.4 Interfacer php et Oracle
Technology Network d'Oracle :
http://www.oracle.com/technology/tech/opensource/
http://www.oracle.com/technology/pub/articles/deployphp/
Oracle et Mac OS X:
http://www.oracle.com/technology/pub/articles/rohrer_macosx_10g.html
php-oracle (FR) :
http://callista.free.fr/php_oracle/php_oracle.php3
Rappel : Oracle est téléchargeable sur le Technet
Oracle : http://technet.oracle.com
Si vous avez des erreurs de connexion de type "TNS coud not
resolve..." voyez les user notes du manuel php.
9.5 Interfacer php et Sybase
Avec Windows : http://www.jf-lebon.com/
9.6 Sites en français
phpindex (FR): http://www.phpindex.com/
et en particulier la FAQ de phpindex : http://www.phpindex.com/faq/
Comment ça marche (FR): http://www.commentcamarche.net/
phpfrance (FR) : http://phpfrance.com/
Site de Christophe Lauer (FR) : http://clauer.free.fr/
phpdebutant.org (FR) : http://www.phpdebutant.org/
phpinfo(non maintenu): http://fr2.phpinfo.net/
Developpez.com : http://php.developpez.com/cours/
Cours et sécurité http://www.saphirtech.com/cours.html
9.7 Sites en anglais
Google. Une recherche bien ciblée vous donnera souvent beaucoup de scripts ou d'informations.
http://www.google.com
SourceForge : http://www.sourceforge.net
PKB PHP Knowledge BASE (ENG) mais sections en en français :
http://www.faqts.com/knowledge-base/index.phtml/fid/51/
PHP Classes Repository (ENG) :
http://www.phpclasses.upperdesign.com/
PHP Builder (ENG) : http://phpbuilder.com
PHP Club (ENG + RU ): http://phpclub.unet.ru/
PHP Wizard (ENG) : http://www.phpwizard.net/
Weberdev (ENG) : http://www.weberdev.com/
Hot Scripts (ENG) :
http://www.hotscripts.com/PHP/Scripts_and_Programs/
Site de Hans Anderson (ENG) : http://www.hansanderson.com/php/
Le code d'un moteur de recherche et d'indexation en php y est
disponible.
Contenu de cette
section
10. Ressources connexes
Contenu de cette section
10.1 Problèmes avec un hébergeur
Avant tout, le support technique de cet hébergeur !!
Amen
Web : http://www.amen.fr
Contact : http://support.amen.fr/contact/
Support : http://support.amen.fr/
OVH
Web : http://www.ovh.com/
Support : http://www.ovh.com/fr/support/
Online
Web : http://www.online.fr
Contact Technique : support@online.net
Contact Commercial : hebergement@online.net
Support : http://www.online.fr/support/fr/
Free
Web : http://www.free.fr
Support : http://support.free.fr/
Forez
Web : http://www.forez.com/portail/
Contact : webmestre@forez.com
Nexen :
Web : http://www.nexenservices.com/
Support : http://www.nexenservices.com/
En complément :
- certains prestataires
disposent de newsgroups privés et autres listes de
diffusion.
C'est le cas en particulier de Proxad (Free et Online) avec
news:proxad.online.hebergement (vous devez disposer d'un compte).
Ne pas hésitez à y aller.
- ne pas négliger
le forum fr.reseaux.internet.hebergement souvent plus adapté que fclphp
(genre coup de gueule, demande de renseignements, etc.). Les
principaux hébergeurs y sont souvent assez actifs.
10.2 Référence HTML
Norme 4.0 du W3C : http://www.w3.org/TR/REC-html40/
All Html (en français) : http://www.allhtml.com/
Papier : HTML Pocket Reference, Jennifer Niederst, ed. O'Reilly
10.3 Problèmes avec du SQL, MySQL,
Postgres, Oracle, Sybase, etc...
Le newsgroup qui permettra d'obtenir les réponses
pertinentes : news://fr.comp.applications.sgbd
La documentation MySQL (en français en milieu de page et en anglais): http://dev.mysql.com/doc/
Le technet Oracle : http://technet.oracle.com/
(inscription gratuite, pas de spam à outrance constaté,
Oracle 8i à télécharger gratuitement pour
développement sous unix)
Le support Sybase :
http://www.sybase.com/support/
(inscription gratuite, pas de spam à outrance constaté)
10.4 Ouvrages "papier"
Oracle Design Dave Ensor and Ian Stevenson ed. O'Reilly
Contrairement à son titre, cet ouvrage est très
généralist sur les SGBDR et en particulier traite
clairemnt et simplement des Formes Normales de Codd. 500+ pages, env
320F. Ne pas confondre avec sa mise à jour Oracle 8i.
10.5 Problème de configuration
Apache, IIS...
Le newsgroup approprié
news://fr.comp.infosystemes.www.serveurs
10.6 Request For Comments
Les RFC (Request For Comment) définissent les protocloes
utilisés quotidiennement par nos lecteurs de news et autres
navigateurs. Elles sont toutes disponibles sur http://www.faqs.org/faqs/
Des grands classiques :
http : RFC 2616
nntp : RFC 977
Contenu de cette
section
11. Génération de graphiques
Contenu de cette section
11.1 GD Lib
Il est possible d'afficher des statistiques sous forme de graphe
avec PHP. Intéressez vous pour ceci à la GD LIB.
Il
est à noter qu'à cause de problèmes de
copyrights et de décalage entre PHP et la GD lib, vous pouvez
avoir des problèmes de compilation.
GD Lib :
http://www.boutell.com/gd/
La GD Lib possède de nouveau le support des GIFs.
11.2 Bibliothèques
Comparatif : http://cyberzoide.developpez.com/php4/graphismes/
Des bibliothèques s'appyant sur la GD lib :
vh graph : http://www.vhconsultants.com/
JpGraph : http://www.aditus.nu/jpgraph/
Vagrant : http://vagrant.sourceforge.net/
PHPLOT : http://www.phplot.com/
11.3 Redimensionner une image
http://fr2.php.net/manual/en/function.imagecopyresized.php
Et bien lire les user notes, qui sont (comme souvent)
intéressantes, avec beaucoup d'exemples de code, des patches
pour l'amélioration de la qualité des thumbnails,etc...
En particulier :
- Vous pouvez recompiler la GD lib ? Du code C et les moyens de patcher sont donnés
- Vous ne pouvez pas patcher la GD lib ? Ce sera moins performant, mais du code 100% PHP est disponible,
donné par rze at counter-strike dot net le 11-Jul-2001.
Des exemples de manipulation sur
http://clauer.free.fr/resphp.html
(au milieu de la page)
11.4 Flash dynamique
PHP Peut également générer des animations flash à la volée.
Exemple d'application aboutie (vérifiez la license): http://www.maani.us/charts/
Contenu de cette
section
12. Bugs php ?
Contenu de cette section
12.1 Comportement bizarre : un bug PHP ?
Quand un script se comporte étrangement, la probabilité
la plus forte est que c'est votre script qui se plante, ou que les
permissions des fichiers que vous traitez sont mauvaises.
Néanmoins,
il y a des bugs (ou des "problèmes résiduels"
((C) A.F. 2000)...) aussi dans PHP, il peut donc être
intéressant de les connaître, surtout si vous utilisez
une version un peu ancienne de PHP.
La liste officielle des
bugs déclarés est disponible sur le site de PHP :
http://bugs.php.net/
Contenu de cette
section
13. Les concurrents de PHP
Contenu de cette section
13.1 PHP et ASP
Une magnifique tarte à la crème qui mobilise
beaucoup d'électrons, l'éternel débat sur
"lequel qu'est le mieux ?" a déjà largement
fait transité des Mo. Avant de le relancer, vous pouvez
consulter :
[Stratégie de développement}
Analyse comparative PHP / ASP
en date du 01-08-200 par
leylek@onera.fr
ID
4Muh5.3432$_y2.5664889@nnrp5.proxad.net
php versus asp
en
date du 02-02-2001 par Théo
ID 95ek7q$2jp$1@nnrp1.deja.com
Php Vs Asp en date du 17-07-2001 par par rage
ID
3B544BC6.49C43EB1@caramail.com
Ces articles sont
disponibles sur http://groups.google.com
et http://www.phpindex.com/ng/ng_index.php3?c=fciwap
13.2 Benchmarks sur les plateformes web dynamique
Quelques benchs :
http://www.chamas.com/bench/
Contenu de cette section
14. Génération de PDF
Contenu de cette section
14.1 Comparatif des solutions existantes
Olivier PLATHEY a présenté un excellent comparatif des solutions
au Forum PHP 2002 de l'AFUP : http://www.afup.org/forumphp2002/fpdf.pdf
14.2 Modification
Outre la pdflib et la clibpdf , fpdi permet d'ajouter des données dans un PDF.
http://fpdi.setasign.de/
15. Compiler / encoder ou "obfusquer" des scripts PHP
Contenu de cette section
15.1 Ne pas livrer son code PHP en clair
Il est classique de devoir livrer des scripts PHP en clair, que n'importe qui ayant
accès à la machine peut ensuite lire et modifier.
Mais il est également possible de :
- rendre le code source moins lisible avec un "obfuscateur". Il s'agit principalement de renommer les
variables, fonctions, classes et méthodes, de supprimer les commentaires et la mise en forme du code.
Du code "obscurci"/obfusqué" ne nécessite aucune instalation d'outils supplémentaires
pour être exécuté.
- precompiler le code source en op-code lisible uniquement par le moteur d'exécution
de PHP, le Zend Engine. On est alors dans une situation similaire à la livraison d'une multitudes de .class
en java, à ceci près que le reverse engineering est beaucoup plus complexe.
En juillet 2005, il n'existe pas de moyen fiable public de revenir au code source d'origine.
L'utilisation d'encoders qui produisent de l'op-code nécessitera l'instalation en plus de PHP
du Zend Optimizer (gratuit).
Dans certains cas, l'utilisation d'encodeurs permet de :
- gagner un temps énorme de recompilation. Au lieu que le moteur de PHP doive, à *chaque* requête, recompiler tous les scripts, ils sont compilés une bonne fois pour toutes.
- être couplé à un système de gestion de license et de nombre d'utilisateurs simultanés, etc...
Beaucoup des solutions d'encodage proposées ci-dessous sont payantes.
ATTENTION DANS LES DEUX CAS : les mots de passe peuvent néanmoins être lus en clair.
Quelques benchs :
http://meta.wikimedia.org/wiki/PHP_caching_and_optimization
http://www.phpindex.com/: les solutions de cache ou directement
http://www.phpindex.com/download/BenchWeb_V1.1.pdf
15.2 Zend Encoder
C'est la solution de la société ZEND TECHNOLOGIES qui a développé le
coeur de PHP 4 et PHP 5. http://www.zend.com/
15.3 ionCube
Une solution d'encodage "à la carte" pour quelques scripts est également disponible.
http://www.ioncube.com/
15.4 phpSHIELD
http://www.phpshield.com/
15.5 turkMMcache / eAccelerator
Le développeur principal de turkMMcache ayant été embauché par ZEND, le projet,
qui malgré son nom possède bien une solution d'encodage (cache d'op-code), a été repris pour donner eAccelerator. http://eaccelerator.net/
15.6 bcompiler
PHP bytecode Compiler. Il s'agit d'une extension standard ("experimental" en juillet 2005).
http://fr2.php.net/manual/en/ref.bcompiler.php
15.7 APC
Alternative PHP Compiler. http://apc.communityconnect.com/
ou directement : http://pecl.php.net/package/APC
15.8 POBS
PHP Obfuscator. Il ne s'agit pas d'un encoder. http://pobs.mywalhalla.net/