FAQ fr.comp.lang.php
Mise à jour : 18 mars 2003
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 Miroirs
Cette FAQ est également disponible sur http://www.phpindex.com/fciwap/ et http://fciwap.phpheaven.net/
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 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.5 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.
N'hésitez pas à nous contacter 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.
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://dev.skamp.net/hebergeurs/ le
détail des configurations (phpinfo) des principaux gratuits français.
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'Apache :
http://lwest.free.fr/doc/php/configuration_NT_fr.html
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érrement 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://www.php.net/manual/en/install.netscape-enterprise.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.
-
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=$_GET['toto']; pour que $toto
soit disponible. Noter les simples quotes autour de 'toto'.
Voir la documentation sur http://www.php.net/manual/en/language.variables.external.php
[en anglais]
pour plus d'informations.
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://www.php.net/manual/function.include.php [en anglais]
ou http://www.php.net/manual/fr/function.include.php [en français]
Manuel pour require ( ) http://www.php.net/manual/function.require.php [en anglais]
ou http://www.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)
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 include("../titi.inc"); dans le fichier
toto.php3, alors, le chemin de titi doit être relatif à toto.php3. 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 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 ?> du
script 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 : www.php.net/manual/function.header.php [en anglais] ou www.php.net/manual/fr/function.header.php
[en français]
2.12 Remplacer les retours chariots
dans une chaine
$chaine = ereg_replace("(\r|\n){1,2}", " ", $chaine);
2.13 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.devshed.com/Server_Side/Administration/RegExp/page1.html
http://www.webmasterbase.com/article/974
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.14 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.15 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://www.php.net/manual/en/language.operators.errorcontrol.php[EN]
ou http://www.php.net/manual/frlanguage.operators.errorcontrol.php[FR]
ATTENTION : il vaut mieux GERER les erreurs que de les IGNORER.
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.
3.2 [souvent HS] Problèmes de connexion
à MySQL
Manuel de MySQL (FR): http://dev.nexen.net/docs/mysql/annotee/manuel_toc.php
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].php3 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 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 la section 6 du manuel http://www.mysql.com/documentation/mysql/commented/manual.php?section=Privilege_system
[en anglais] ou
http://dev.nexen.net/docs/mysql/annotee/manuel_Privilege_system.php#Privilege_system
[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 print("</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 != TRUE)
/* NB : on peut faire appel à la fonction mysql_error() ou mysql_errno() pour obtenir le
message de retour de la base */
{
print("Connexion impossible.\n");
include("std_footer.php3");
fx_footer("parametre1","parametre2");
exit();
}
if(mysql_select_db("votre_base",$l_dad)!=TRUE)
{
print("Database inaccessible.\n");
include("std_footer.php3");
fx_footer("parametre3","parametre4");
exit();
}
return ($l_dad);
}
Pour chaque nouvelle connexion, appeler directement $DAD=fx_std_connect(
);
Il va de soit que cette fonction doit être définie dans chaque script
où elle est appelée,
le plus simple étant de faire un include("std_connect.php3"); où std_connect.php3
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 (DOCUMENT_ROOT)
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...
parse error on line 55 : une erreur de parsing
(en français dans le texte) est une erreur de syntaxe php. 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.
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 php3.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.php3");
break;
case "EN" : include("EN_mesg.php3");
break;
case "DE" : include("DE_mesg.php3");
break;
default : print("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.php3 : define(msg1,"Bonjour");
Dans EN_mesg.php3 : define(msg1,"Hello");
Dans DE_mesg.php3 : 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://www.deja.com/home_ps.shtml
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").
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://www.php.net/manual/features.file-upload.php [en anglais]
ou http://www.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.php3" 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://www.php.net/manual/en/function.is-writeable.php [en anglais]
ou http://www.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://www.php.net/manual/function.move-uploaded-file.php
http://www.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.), 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
http://support.free.fr/faq/web.html#7
si la solution officielle "Form2Mail" ne répond pas à vos besoins, intéressez-vous
à la solution 'Protomail' : http://samuel.kabak.free.fr/scripts/protomail.html%20target=
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
Le MEILLEUR moyen de vérifier la validité d'une adresse
email, c'est de lui en envoyer un pour demande de confirmation
d'inscription.
On peut néanmoins dans un premier temps vérifier la syntaxe de l'adresse,
mais cela est plus compliqué si on veut être pointu.
A titre d'exemple des regexp, on peut considérer le test ci dessous, permettant
de juger assez grossièrement si la chaîne $email semble être une
adresse valide.
$email=toto@coincoin.com;
if (ereg("^(.+)@(.+)\\.(.+)$",$email, $tableau)
{...}
Pour une fonction beaucoup plus fine, utilisez le code proposé par Marc
Meurrens en suivant ce lien : http://www.cgsa.net/php/index.php
Concernant le nom de domaine, c'est encore moins fiable. A part vérifier
que la résolution DNS renvoie bien quelque chose par checkdnsrr( ) mais
ça peut prendre du temps, on ne sait pas faire grand chose.
5.4 Forums usenet
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://articles.phpheaven.net/article.php3?id_article=2>
- pour imap, le manuel :
<http://www.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
Il existe des projets "tout prêts" et gratuits. Par exemple
:
- phorum http://www.phorum.org/
- agora http://w-agora.araxe.fr/
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/
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/
Sites dediés (en français) :
http://cty.mandrake.org/davduf/
http://phpnuke.edazine.com/
Alternatives diverses :
http://www.phpscripts-fr.net/?page=scripts&cat=Portails
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
A lire : http://php.net/manual/en/ref.session.php ou en français http://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 est l'adresse IP du client.
Dans le cas où il y a un (au moins) proxy, les variables $HTTP_X_COMING_FROM
et $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/
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://support.free.fr/web/pperso/restriction_acces.html
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://php.net/
et http://php.net/docs.php (anglais
et français) dont la référence rapide : http://www.php.net/quickref.php
Traduction chez Nexen : http://dev.nexen.net/docs/
9.2 Ouvrages "papier"
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. Voir http://www.cgsa.net/php/campusPress
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
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/sybase/
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/
ilovephp (FR)(oui, en français!) : http://ilovephp.com/
phpdebutant.org (FR) : http://www.phpdebutant.org/
cgsa / Marc Meurrens : http://www.cgsa.net/
phpinfo(non maintenu): http://www.phpinfo.net/
9.6 Sites en anglais
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/
Darkseed (ENG) : http://www.darkseed.net/main.html
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.fr/
Contact Technique : tech@ovh.net, hotline@ovh.net
Contact Commercial : ventes@ovh.net
Support : http://www.ovh.fr/faq/
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/
Contact : http://www.free.fr/corporate/contact.html
Support : http://support.free.fr/web/
Forez
Web : http://www.forez.com/portail/
Contact : webmestre@forez.com
Nexen :
Web : http://www.nexenservices.com/
Contact : http://www.nexenservices.com/contact/email.php
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 fr.reseaux.internet.hebergement souvent plus adapté
que
le 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 anglais: http://www.mysql.com/doc.html
La documentation MySQL traduite chez Nexen : http://dev.nexen.net/docs/mysql/annotee/
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://faqs.org/
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/
Pour vous procurer d'anciennes versions de la GD Lib, avec support des
GIFs :
http://rufus.w3.org/linux/RPM/GByName.html
11.2 Bibliothèques
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/
11.3 Redimensionner une image
http://www.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)
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
Quelques benchs :
http://aldev0.virtualave.net/php-perl-benchmarks.html
http://www.chamas.com/bench/hello_bysystem.html
http://phpweblogs.com/php_vs_asp
Contenu de cette section
|