Initiation à PHP

Transcription

Initiation à PHP
Introduction à PHP
Master Créations Images et Multimédia Multilingue / CAWEB
1.Historique
Php est né du fruit du travail de Rasmus Lerdorf , une première version du
langage voit le jour en 1994. La diffusion du langage debute dès 1995. Le nom
initial du projet ( « Personal Home Page tools » sera rebaptisé « hypertext
préprocessor ») . A l'heure actuelle ce langage est devenu très populaire chez
les web designers, simple d'approche et surtout très puissant , il évolue
constamment grâce à une communauté de développeurs très importante.
On est aujourd’hui à la version 5 du langage
PHP est distribué librement et gratuitement sous licence GNU GPL
il est téléchargeable sur http://www.php.net
1.Historique
Php est né du fruit du travail de Rasmus Lerdorf , une première version du
langage voit le jour en 1994. La diffusion du langage debute dès 1995. Le nom
initial du projet ( « Personal Home Page tools » sera rebaptisé « hypertext
préprocessor ») . A l'heure actuelle ce langage est devenu très populaire chez
les web designers, simple d'approche et surtout très puissant , il évolue
constamment grâce à une communauté de développeurs très importante.
On est aujourd’hui à la version 5 du langage
PHP est distribué librement et gratuitement sous licence GNU GPL
il est téléchargeable sur http://www.php.net
1.2 Principe de fonctionnement
•
PHP est avant tout un langage de script (scripting).
•
Le code inséré dans les pages HTML, est exécuté par le serveur sous réserve
que les pages portent l'extension .php3 .php ou .php4. Le fichier contenant du
code php est hébergé sur le serveur ; lors d’une requête HTTP , le code HTML
est retourné tel quel et le code php est extrait et exécuté par le serveur . Les
résultats seront intégrés au flot HTML.
•
Très simple à appréhender car possédant une syntaxe claire et très proche du
langage C, le PHP reste une solution qui conviendra aux débutant comme aux
professionnels, pour dynamiser un site Web ou l'interfacer avec une Base de
données.
1.3 Php et la concurrence
•
Le PHP utilise une syntaxe très simple car elle reste très proche du langage C,
langage maîtrisé par la plupart des développeurs.
•
Les autres langages du web sont :
- ASP : c’est la réponse de Microsoft à PHP, ASP utilise une syntaxe basée
sur VBScript (Version allégée de Visual Basic)
- PERL : C’est un langage de script puissant, adapté à Internet mais difficile
à maîtriser
- CGI : Composants exécutables, rapide mais spécifiques à la plate formeserveur et pose souvent des problèmes de securité tout en étant complexe à
développer.
- JAVASCRIPT : Javascript est quand à lui interprété par le logiciel client ( =
le navigateur ) des problèmes de sécurité sont inhérents à ce mode de
fonctionnement
- RUBY : Langage de script qui peu être utilisé pour le dvt web on parle
surtout de RoR ( Ruby on Rails projet un peu jeune mais prometeur ! ) un
framework de dvt web basé sur Ruby.
L'appelation « ruby » vient d'un jeu de mot sur Perl. Ruby utilise la
programmation dite MVC ( modèle vue contrôleur )
- Python : Comme python c'est un langage de script orienté objet
qui utilise le modèle MVC on le couple souvent à Django ou Zope
pour le dvt web.
- JAVA, Webdev (...)
1.3.1 ASP :
<html>
<head>
<title>De l'ASP dans le cours de ToMa !!!!!!</title>
</head>
<body bgcolor="white" text="black">
<%
Dim strMessage
strMessage = "Hello les copains"
Response.Write (strMessage)
Response.Write ("<br>")
Response.Write ("Il est : " & Time())
%>
</body>
</html>
1.3.2 PERL :
#!/usr/local/bin/perl
print("content-type : text/html\n\n");
print("Hello les copains !");
($secondes,$minutes,$heure)=localtime(time);
print(''Il est $Heure:$minute:$secondes'');
1.4 Intégration et syntaxe de PHP
•
Avant d’utiliser PHP il faut s’assurer que notre hébergeur le supporte à moins
qu’on désire travailler localement - installation possible sous windows du pack
easyphp ( http://www.easyphp.org ) ou sous linux il faut utiliser le systeme de
packetages ( rpms ) ou les fichiers binaires.
•
Les hébergeurs Wanadoo, Free… supportent le PHP (pas intégralement car
certaines fonctions comme mail() ne sont pas toujours activées).
•
Intégrer du php dans une page est très simple à réaliser , une page type combine
souvent HTML et PHP , il faut alors introduire une notation particulière pour
distinguer les deux langages .
1.4.2 Integration dans une page HTML
Il existe 4 méthodes pour intégrer PHP à l'intérieur d’un document HTML :
A l'aide des tags courts <? et ?>
<? echo (‘’ hello world !!!!"); ?>
A l'aide des tags <?php et ?>
<?php echo (" hello world !!!!"); ?>
A l'aide de délimiteur de type ASP (<% et %>)
<% echo (" hello world !!!! "); %>
A l'aide de la balise <script language="...">
<script language="PHP">
<!-echo (" hello world !!!!");
//-->
</script>
1.4.3 Notions importantes
•
•
Extensions
Selon la version du langage, les extensions sont différentes :
version 2 (php) : ".phtml" version 3 : ".php3" version 4-5 : ".php" “.php4” …
Selon les paramétrages du serveur, les anciennes extensions sont reconnues ou
non.
Les Variables : C’est une zone de mémoire vive ou on enregistre des
informations comme du texte ou des nombres ...
•
Les règles à retenir :
chaque ligne doit se terminer par un point-virgule (";")
chaque variable commence par le signe dollar ("$")
•
Les commentaires peuvent prendre soit une ligne, soit plusieurs lignes.
sur une ligne :
//commentaire avec deux barres obliques
#commentaire avec le signe dièse
sur plusieurs lignes,
/*
lignes de commentaires
*/
1.4.4 Premier script
<?
echo ‘’<marquee>HELLO WORLD</marquee> ‘’;
?>
1.5 Les types de données
•
•
•
•
Les nombres entiers (integer).
$nombre = 123;
Les nombres à virgules (doubles).
$a = 123.456;
Les chaînes de caracteres (string)
$chaine = ‘’desscimm";
Les tableaux (array )
$chiffres = array(6,7,5,3);
$coolvibes = array("I","won’t","do","what","you","tell","me");
echo $coolvibes[3] ;
1.5.2 Notion de tableau
• Les tableaux sont très important à maîtriser en
PHP, car ce langage est souvent lié à des
bases de données. Ces bases de données
retournent plusieurs valeurs, et généralement
sous forme de tableau.
$site[0] = ‘’www.google.fr";
$site[1] = ‘’www.supersite.fr";
$site[2] = ‘’www.superloose.com";
1.5.3 Les variables
En PHP, les variables sont déclarées par le signe '$'. Elles servent à stocker des données
dans le script, pour les réutiliser plus tard.
<?php
/*
Definition des variables
*/
$a = 2;
$b = 4;
/* Addition */
$addition = $a + $b; // $addition vaut 6
echo $addition;
/* Soustraction */
$soustraction = $b - $a; // $soustraction vaut 2
/* Multiplication */
$multi = $a * $b; // $multi vaut 8
echo $multi;
/* Division */
$div = $b / $a; // $div vaut 2
echo $div;
?>
• Comme en Javascript , on peut incrémenter ( ou le contraire ) la valeur
d'une variable de 1 en écrivant : $variable++; ou $variable--;
•
1.5.4 Les variables d’environnement
•
Il est possible en PHP d'obtenir des informations aussi diverses que le nom du
navigateur de l'internaute ou le serveur utilisé. Ces informations sont stockées
dans des variables spéciales appellés "variables d'environnement". La
commande "phpinfo()" récapitule toutes ces variables :
<?
phpinfo();
?>
$REMOTE_ADDR par exemple, contient l'adresse IP du client
$HTTP_USER_AGENT contiendra le nom du navigateur utilisé
1.5.6 Opérations sur les chaines de caractères
• En PHP, la concaténation de deux chaînes se
fait à l’aide du symbole "."
<?
$a = 'php c\’est'; $a = ''php c'est top'';
$b = $a . ' top !';
echo $b;
?>
1.6 Les fonctions
•
PHP propose de nombreuses fonctions, mais on peut definir ses propres
fonctions à l’aide de function().
•
Exemple fichier fonction.php :
<?
function Arial($taille,$couleur,$texte)
{
print("<font face=Arial size=".$taille." color=".$couleur.">".$texte."</font><br/>");
}
?>
1.6 Les fonctions
Exemple d’un script utilisant notre fonction
<?
function Arial($taille,$couleur,$texte)
{
print("<font face=Arial size=".$taille." color=".$couleur.">".$texte."</font><br/>");
}
Arial("2","red", "super ...");
Arial("3","#0F74A3", " Genial ...");
?>
1.7 Include et Require
• Les deux fonctions include et require
permettent d'insérer dans un script le code
contenu dans un autre fichier.
Ex : <?php include "mesfonctions.php";?>
<?php require "http://www.cool.com/rastafari.php";?>
1.7 Include et Require
•
Dans notre exemple :
Fichier index.php :
<?
include "MesFonctions.php";
Arial("2","red", "super ...");
Arial("3","#0F74A3", " Genial ...");
?>
Fichier MesFonctions.php :
<?
function Arial($taille,$couleur,$texte)
{
print("<font face=Arial size=".$taille." color=".$couleur.">".$texte."</font><br/>");
}
?>
1.7.2 Différences Include et Require ?
•
Avant la version 4.0.2, la méthode mot "require" pratiquait l'inclusion du fichier au moment de l'analyse
(interprétation par php) et non de l'exécution du script.
•
Dans les versions actuelles la méthode include encas de non existence du fichier inclus affiche un
avertissement et continue l'exécution du script alors que require génère une erreur et interrompt le script.
•
Il est donc conseillé d'utiliser la méthode require quand le fichier à inclure est vraiment requis par
l'application php. Si on préfere la méthode include il faut tester l'existence du fichier ou non.
•
Si le fichier n'existe pas et qu'on utilise include, la fonction include renverra false ( = booléen )
<?php
if( file_exists( 'SuPaFicHier.php' ) ) include 'SuPaFicHier.php';
else die("erreur fatale"); // die equivalent à exit() exit("erreur fatal");
?>
1.8 Exemples de codes php : passage de variables à un script depuis un formulaire
Fichier formulaire.html :
<form name="formulaire" method="post" action="page.php">
ton ptit nom : <input type="text" name="nom">
<input type="submit’’ value=‘’envoyer’’>
</form>
Fichier page.php :
<?php
echo "bonjour ".$nom;
?>
<?php
echo "bonjour ".$_POST['nom'];
?>
1.8 Exemples de code php : afficher la date
•
La fonction date permet de décrire une date en retournant une chaîne de caractères sous le format
désiré. Cette date est exprimée en fonction du timestamp qui est le nombre de secondes écoulées
depuis le 1 Janvier 1970 (époque UNIX)
echo time(); //donnes le nb de secondes écoulées
Syntaxe : Chaîne date("format", "timestamp")
L'argument timestamp est optionnel. S'il est vide, l'heure et la date courante seront utilisées.
•
Constantes de formatage :
a am ou pm
A AM ou PM
dJour du mois, avec conservation des zéros "01" et "31"…
D Jour de la semaine, abrégé en trois lettres ( en anglais "Mon" "Fri" … )
F Mois en anglais et en entier "january" ….
h Heure, de 1 à 12
H Heure, de 0 à 23 ( format 24h)
i Minutes
J Jour du mois, avec suppression des zéros
L Jour de la semaine
m Chiffre du mois, de 01 à 12
M Abréviation du nom du mois en anglais
Y Année, sur quatre unités "2001"
1.8 Exemples de codes PHP
•
<?php
$datedujour=date(" j/m/Y");
echo $datedujour;
?>
1.8 Exemples de codes : dates et locales
•
strftime --Formate une date/heure locale avec les options locales
string strftime ( string format [, int timestamp] )
Les mois et jours de la semaine, et toutes les chaînes dépendantes de la
langue sont fixées avec la commande setlocale()
Pour le paramètre format :
%a : nom abrégé du jour de la semaine
%A : nom complet du jour de la semaine
%b : nom abrégé du mois
%B : nom complet du mois
%d : jour du mois en numérique (intervalle 01 à 31)
%H : heure de la journée en numérique, et sur 24-heures
%I : heure de la journée en numérique, et sur 12- heures
%j : jour de l'année, en numérique (intervalle 001 à 366)
%m : mois en numérique (intervalle 1 à 12)
%M : minute en numérique
%S : secondes en numérique
%T : l'heure actuelle (égal à %H:%M:%S)
1.8 Exemples de codes : dates et locales
<?php
echo strftime("En Finlandais est ");
setlocale(LC_ALL, "fi_FI.UTF-8");
echo strftime("%A, en Français ");
setlocale(LC_ALL, "fr_FR.UTF-8");
echo strftime("%A et en Allemand ");
setlocale(LC_ALL, "de_DE.UTF-8");
echo strftime("%A");
?>
1.8 exemples de codes PHP : date de maj
• Ce petit script va afficher la dernière date de mise à jour d’une page
html à l’aide de la fonction DATE de la fonction filemtime et d’une
variable d‘environnement $SCRIPT_FILENAME
• <?
echo("Dernière modification le ");
echo(date("d/m/Y à H:i",filemtime($_SERVER['SCRIPT_FILENAME'])));
?>
2.0 Complément sur la gestion des variables
• Un changement dans PHP pourrait rendre son
apprentissage plus complexe. Depuis la
version 4.2, la valeur par défaut de
register_global est à Off cf php.ini ou
phpinfo();
• Une variable envoyée par un formulaire
(method=POST name =motdepasse) ne sera
plus accessible avec $motdepasse mais avec
$_POST['motdepasse'].
2.0 Complément sur la gestion des variables
•
Pourquoi ?
– Pour sécuriser le code et empêcher l ’accès et la
manipulation des variables .
• Le code est en soi plus stable quand on gère les variables de cette
manière , on sait exactement ce que l ’on fait Il faut constamment
faire attention aux entrée (input) utilisateurs ( formulaires… )
• Pour aller plus loin :
http://www.php.net/release_4_1_0.php
( section SECURITY: NEW INPUT MECHANISM )
http://www.php.net/manual/fr/security.registerglobals.php
2.1 REGISTER GLOBAL
• La configuration du paramètre register_global est contrôlée dans le
fichier de configuration php.ini.
• Infos : http://www.php.net/manual/fr/configuration.php
• Le paramètre register_global peut prendre deux valeurs, On et Off.
Avant la version 4.2.0 la valeur par défaut était On mais cela a
changé et il faut adapter son code pour les nouvelles versions ou
les mises à jour de php chez votre hebergeur.
• On peut voir la valeur du parametre REGISTER GLOBAL à l ’aide
de la fonction phpinfo()
2.2 L ’origine des variables
•
•
Par les url : une des façons les plus simples pour faire transiter des variables de
pages en pages est l'insertion dans l'URL. On appelle ça communément la
méthode GET.
Anatomie d'une URL
http://mastercaweb.u-strasbg.fr/script.php?variable=toto&foo=bar
– http:// : C'est le protocole utilisé pour communiquer.
– mastercaweb.u-strasbg.fr/ : C'est le nom d'hote, le nom DNS ou l'adresse IP
du serveur référencé par cette url.
– script.php : C'est le nom du script.
– ? variable=toto &foo=bar : Il s'agit de la query ( requete) Elle permet
d'envoyer des informations au script script.php
•
Avec la configuration register_global à On, le script "script.php" aurait
automatiquement $var = 'test', $foo='bar'. Ces variables seraient des
variables globales pour le script auquel vous accédez.
2.2 L ’origine des variables
• Toutes les fois qu'un paramètre est indiqué dans l ’URL du script,
PHP créé un tableau global nommé $HTTP_GET_VARS.
• Il s'agit d'un tableau associatif. En prenant l'exemple précédent on
aurait :
• $HTTP_GET_VARS = array ('variable' => 'toto', 'foo' => 'bar');.
• Depuis la version 4.1.0 une variable globale nommée $_GET
contient exactement la même chose que $HTTP_GET_VARS.
• Ce tableau est nommé superglobal
2.2 L ’origine des variables
• Provenance : Formulaire
• Une autre méthode commune pour passer une
variable à un script est un formulaire sur une page
web.
2.2 L ’origine des variables
• Quand un utilisateur va cliquer sur le bouton "envoyer" le navigateur
va soumettre le formulaire au script "script.php" avec une variable
$foo qui aura la valeur que l'utilisateur aura rentrée.
• Avec la configuration register_global à On, le script "script.php"
aurait automatiquement attribué $foo='bar'.
• De façon similaire à l'exemple précédent sur la provenance URL,
PHP va générer automatiquement une tableau nommé
$HTTP_POST_VARS.
• Dans le cas de notre exemple : $HTTP_POST_VARS['foo'] = 'bar';.
• Depuis la version 4.1.0 une variable globale nommée $_POST
contient exactement la même chose que $HTTP_POST_VARS à
savoir $_POST['foo'] qui aura pour valeur bar.
2.2 L ’origine des variables
• Provenance : Un cookie : les cookies permettent de stocker des
informations sur le disque dur de la machine cliente.
• Dans l'exemple qui suit on va placer un cookie :
/* durée de validité du cookie 24h */
setcookie('foo', 'bar', time()+86400, '', $HTTP_HOST);
• Pour accéder aux valeurs du cookie on utilisera alors
$_COOKIES["foo"] qui nous indiqueras sa valeur ie 'bar'.
2.2 L ’origine des variables
• Provenance : Environnement ou Serveur : Le système d'exploitation
ainsi que les serveur Web disposent de nombreuses variables qui
peuvent être utilisées dans un script.
• Une de ces variables les plus utilisées sont : Le nom du script lui
même ainsi que le nom de l'hôte.
• PHP créé automatiquement deux tableaux associatifs
$HTTP_ENV_VARS et $HTTP_SERVER_VARS.
• Apres PHP 4.1.0 les mêmes tableaux sont nommés : $_ENV et
$_SERVER. ( voir fonction print_r )
2.3 Utilisation des superglobales
• Si vous utilisez plus d'une fois des variables passées en paramètre
vous pouvez tout simplement les assigner à une variable.
ex : $superCool = $_GET[superCool];
• Cela évitera de faire appel à des superglobales à chaque fois.
• Cette technique peut aussi permettre d'éviter de recoder tous les
scripts en assignant les bonnes valeurs aux bonnes variables en
début de script.
2.3.2 Pourquoi superglobales ?
• Normalement une variable utilisée dans une fonction est locale à
celle ci.
• Si on veut utiliser la variable globale dans une fonction
global $superCool;
• Les superglobales sont des exceptions à cette règle. Vous pouvez
utiliser les superglobales $_GET, $_POST, $_COOKIE, $_ENV,
$_SERVER et $_SESSION sans avoir besoin de les déclarer en
globales.
2.4 Conclusion
$_GET
contient les variables passées par la méthode GET
$_POST
contient les variables passées par la méthode POST
$_COOKIE contient les variables HTTP cookie
$_SERVER
contient les variables serveur (par ex.
REMOTE_ADDR)
contient les variables d'environnement
• $_ENV
Une fusion des variables GET. POST, COOKIE.
• $_REQUEST
En d'autres mots toutes les informations qui arrivent de l'utilisateur.
Et d'un point de vue purement sécurité, ce n'est pas sûr.
contient toutes les variables HTTP
• $_SESSION
enregistrées par le module de gestion de session
•
•
•
•
3.1 Les structures de controle
<?
while ( love & passion } {
for( fight = 0 ; rights < freedom ; rights++ )
fight = standup( rights );
free( babylon );
}
?>
3.1 Les structures de controle
if (condition)
{exécute le code}
<?
// On affecte une valeur, à une variable.
$un_nombre = 15 ;
//Condition :
if ( $un_nombre > 9) { // "Si"
// on execute le code suivant.
echo "Superieur à 9";
}
?>
3.1 Les structures de controle
if (condition)
{exécute le code}
else
{exécute le code}
<?
// On affecte une valeur, à une variable.
$un_nombre = 5 ;
//Condition :
if ( $un_nombre > 9) { // Si
// on execute le code suivant.
echo "Superieur à 9";
}else{ // Ou
echo "Alors Inferieur à 9";
}
?>
3.1 Les structures de controle
if (condition)
{exécute le code}
elseif (condition)
{exécute le code}
else
{exécute le code}
<?
?>
// On affecte une valeur, à une variable.
$un_nombre = 5 ;
//Condition :
if ( $un_nombre > 9) { // "Si"
// on execute le code suivant.
echo "Superieur à 9";
}elseif( $un_nombre < 2) { // ou si
// alors sinon on execute le code suivant.
echo "Inferieur à 2";
}else{ // Ou
echo "le nombre est inferieur à 9 et est superieur à 2 "; }
3.1 Les structures de controle
•
for(évaluation de l'expression (expr1); condition(expr2) ; expr3 ) { exécute le code}
<?
for ($i=0; $i < 10 ; $i++ ){
echo $i . " est inférieur à 10<br />";
}
// Pour la variable $i initialisé à Zéro
// Et si $i est inférieur à 10, on exécute le code entre {}.
// Apres avoir exécuté le code entre {}, on exécute le code expr3, c'est à dire $i++.
// et on reteste la condition
?>
3.1 Les structures de controle
while ( condition )
{exécute le code }
<?
// on initialise la variable '$i' avec la valeur 0
$i = 0;
// Tant que la variable $i est inférieur à 10
while ( $i <= 10 ) {
// on execute le code suivante
// affichage de la variable $i
echo "$i<br />";
// incrementation de la variable , peut se noter aussi $i = $i +1 ;
$i++;
}
?>
3.1 Les structures de controle
• Break
<?
// On initialise $i à 0.
$i= 0;
// Tant que 1, (boucle infinie)
while (1){
// Si $i est supérieur à 10.
if ($i > 10 ) {
// On stoppe le while avec le break.
break;
}
// Affichage d'un message.
echo "Passage en boucle pour la $i eme fois.<br />" ;
// incrementation.
$i++;
}
?>
3.1 Les structures de controle
• foreach(évaluation de l'expression ) {exécute le code}
<?
// On crée une variable $Tableau, et on insére dedans plusieurs éléments.
$Tableau = array("Punk","Post","Hard","Jazz");
// On met le pointeur du tableau au début.
// Pour chaque élément du $Tableau représenté par $rock
$i=0;
foreach ($Tableau as $Rock ) {
// on execute le code.
echo "element $i du tableau : $Rock est un élément du tableau rock !<br />";
$i++;
}
?>
3.1 Les structures de controle
• switch ($variable) { case "valeur": exécute de code; break; }
<?
$valeur = "peace";
switch ($valeur){
// Si valeur est égale à peace on execute le code jusqu'au break.
case "peace": echo "La valeur contenu dans valeur est 'peace'";
break;
case "hate": echo "La valeur contenu dans valeur est 'hate'";
break;
// Si on souhaite executé un morceau de code si la valeur
ne fait pas partie des cases.
default:
echo "Je n'ai pas reconnu la valeur '$valeur'";
break;
}
?>
3.1.2 Operateurs de comparaisons
•
•
•
•
•
•
•
•
•
$a == $b
Egal
TRUE si $a est égal à $b .
$a === $b Identique TRUE si $a est égal à $b et qu'ils sont de même type
(introduit en PHP 4).
$a != $b
Différent
TRUE si $a est différent de $b .
$a <> $b
Différent
TRUE si $a est différent de $b .
$a !== $b Différent
TRUE si $a est différent de $b ou bien qu'ils ne sont pas
du même type. (introduit en PHP 4)
$a < $b Plus petit que TRUE si $a est strictement plus petit que $b .
$a > $b Plus grand TRUE si $a est strictement plus grand que $b .
$a <= $b
Inférieur ou égal
TRUE si $a est plus petit ou égal à $b .
$a >= $b
Supérieur ou égal TRUE si $a est plus grand ou égal à $b .
3.1.3 Les operateurs logiques
• && c'est l'équivalent du ET
Ex: $toto=6;
$titi=3;
($toto < 10 && $titi > 1) retourne VRAI
• || c'est l'équivalent du OU
Ex: $toto=6;
$titi=3;
($toto==5 || $titi==5) retourne FAUX
• ! C'est l'équivalent du NON
Ex: $toto=6;
$titi=3;
!($toto==$titi) retourne VRAI
3.1,4 Création d’un site dynamique en php
•
Cahier des charges : créer l’ossature d’un site web dynamique
•
On utilisera plusieurs fichiers :
–
–
–
–
–
–
Index.php la page qui permettra de générer le site
navigation.htm menu du site
homepage.htm page d’accueil du site
liens.htm liens ouaibes
Cv.htm page avec cv
bas_page.htm affichage du bas de page
3.2 Envoyer des mails en php
• Envoyer un mail en php est très facile , tout se résume en une ligne
, à l’aide de la fonction mail() et de ses paramètres.
• La fonction reçoit un minimum de paramètres , à qui veut on écrire
tout d’abord , ( champ to: ) quel est le sujet du mail ( subject ) , le
contenu de notre message et enfin l’expéditeur (champ from: )
• Le champ ( from: ) permet aussi de spécifier d’éventuels copies
( Cc ) ou copies cachées ( Bcc ).
3.2 Envoyer des mails en php
• Envoyer un mail en php est très facile , tout se résume en une ligne
, à l’aide de la fonction mail() et de ses paramètres.
• La fonction reçoit un minimum de paramètres , à qui veut on écrire
tout d’abord , ( champ to: ) quel est le sujet du mail ( subject ) , le
contenu de notre message et enfin l’expéditeur (champ from: )
• Le champ ( from: ) permet aussi de spécifier d’éventuels copies
( Cc ) ou copies cachées ( Bcc ).
3.2 Exemples d’utilisation de mail()
<?
//On envoie un message à [email protected]
mail(' [email protected] ', 'sujet : admiration !!!', "Bofh président !!\n Trop
bien !!!!!!");
?>
<?
?>
$destinataires = ' [email protected], [email protected] ';
//On sépare les destinataires par une virgule.
$sujet = 'plouf !!!';
mail($destinataires, $sujet, "Trop sympatoche\n kewwwwwwwwwwl ! ");
3.2 adresse de l'expediteur
<?
$destinataire = '[email protected],[email protected]';
$sujet = 'is there someone ?';
$entete = "From: [email protected]\n";
mail($destinataire, $sujet, "Hello \n someone's here ? ",$entete);
?>
<?
?>
$destinataire = '[email protected],[email protected]';
$sujet = 'is there someone ?';
$entetes = "From: [email protected]\n";
$entetes .= "Reply-to: [email protected]\n";
mail($destinataire, $sujet, "Hello \n someone's here ? ",$entetes);
3.2.1 Exemple d’utilisation de mail()
<?php
$to = ‘’[email protected]’’;
$sujet = ‘’I luv ur software’’;
$contenu = ‘’ Just joking man ! ‘’;
$entetes = ‘’From: [email protected]\n‘’;
$entetes .= "Reply-to: [email protected]\n";
$entetes .= "Cc: [email protected] \n";
$entetes .= "Bcc: [email protected] \n";
$reponse = mail($to,$sujet,$contenu,$entetes);
if ($reponse ){
echo "message tipar !!!!!!!";
}
else
{
die( "Mssieur le facteur je crois qu'on a un problème !!!!");
}
?>
3.3 Site dynamique multilingue
• Principe : on va stocker le contenu texte dans des
variables spéciales appelées « constantes » .
• On utilisera un cookie pour retenir la langue choisie par le
visiteur du site
• On pourra determiner la langue à utiliser en fonction d'une
variable d'env. : HTTP_ACCEPT_LANGUAGE .
• On utilisera pour chaque langue un fichier à part pour
faciliter la mise à jour.
3.3 Site dynamique multilingue
•Les constantes :
Ce sont des variables définies à l’aide de la fonction define()
define(‘SUPER_CONSTANTE', ‘valeur de ma super constante');
•Par convention les noms des constantes sont toujours en
majuscules pour les différencier des autres variables de nos scripts.
define(‘SALUTATION’,’Yo c\’est super php!’);
echo SALUTATION;
3.3 Site dynamique multilingue : lang_fr.php
<?php define(‘MSG_BIENVENUE', 'Bienvenue sur mon site’);
define(‘MSG_GENIAL‘,’C\’est super php!’);
define(‘MSG_COPYLEFT‘,’Site fait par moi !’);
define('LIEN_FR','francais');
define('LIEN_EN','anglais');
?>
3.4 Site dynamique multilingue : lang_en.php
<?php define(‘MSG_BIENVENUE', Welcome to my website’);
define(‘MSG_GENIAL‘,’PHP is awesome :!’);
define(‘MSG_COPYLEFT‘,’made by myself’);
define('LIEN_FR','french');
define('LIEN_EN','english');
?>
3.5 Intégration des fichiers choixlang.php
<?
?>
//premier cas pas de cookie ni variable langue initialisée on part sur la langue du navigateur
If((!$_GET['lang'])&&(!$_COOKIE['lang'])){
$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'],0,2);
setCookie("lang",$lang,time()+86400);
}
//deuxieme cas une valeur dans le cookie
Elseif(($_COOKIE['lang'])&&(!$_GET['lang'])){
$lang=$_COOKIE['lang'];
}
//sinon on se base sur la lang affecté en param
Else{
$lang=$_GET['lang'];
setCookie("lang",$lang,time()+86400);
}
// on switch sur lang pour savoir quel fichier inclure switch($lang){
case "fr":
include "lang/lang_fr.php";
break;
case "en":
include "lang/lang_en.php";
break;
default :
include "lang/lang_fr.php";
break;
}
3.6 Notre page web multilingue index.php
<?php
require(‘choixlang.php’);
?> <html>
<body> <?php echo MSG_BIENVENUE; ?> <br/>Avis sur php : <?php echo MSG_GENIAL; ?> <br/>Auteur : <?php echo MSG_COPYLEFT; ?> <br/><br/>
<a href=?lang=fr> <?php echo LIEN_FR; ?>
<a href=?lang=en> <?php echo LIEN_EN; ?>
</body>
</html>
3.7 Les fichiers en PHP
•
Un fichier stocke sur le disque dur des éléments ( textes,images... )
•
Php ignore la structure d’un fichier il traite de la même façon un fichier binaire ( images /
sons / prog… ) qu’un fichier texte.
•
Quand on ouvre un fichier en php on doit indiquer comment php doit evaluer le fichier
( LECTURE - ECRITURE – MODIFICATION )
•
On appelle "pointeur de fichier" la variable qui est affecté de la valeur de la fonction
d'ouverture de fichier :
$fp=fopen("leGentilFichier", 'a+');
fwrite($fp,"Barbatruc !!!!! \n");
3.7 Lecture rapide d’un fichier
• Readfile() : affiche le contenu d’un fichier à l’écran
<?
// affichage à l’ecran de MonSuperFichier.txt
readfile(‘’MonSuperFichier.txt’’);
// affichage url
readfile(‘’http://www.perdu.com/’’);
?>
3.8 Ouverture d’un fichier
La fonction fopen :
fopen(NomDuFichier, ModeOuverture)
• "r" - Ouvre en lecture seule et pointeur de fichier au début.
• "r+" - Ouvre en lecture/écriture et pointeur de fichier au début.
• "w" - Ouvre en ecriture seule - pointeur de fichier au début/réduit la
taille du fichier à 0. Si le fichier n'existe pas, on tente de le créer.
• "w+" - Ouvre en lecture/écriture, pointeur de fichier au début du
fichier réduit la taille du fichier à 0. Si le fichier n'existe pas, on tente
de le créer.
• "a" - Ouvre en ecriture seule; place le pointeur de fichier à la fin du
fichier file. Si le fichier n'existe pas, on tente de le créer.
• "a+" - Ouvre en lecture et écriture; place le pointeur de fichier à la
fin du fichier. Si le fichier n'existe pas, on tente de le créer.
• Fopen renvoie un booléen :
• if (!($f=fopen("exemple.txt","r")))
• exit("impossible d'ouvrir le fichier !!!!");
3.8.2 Fermeture d’un fichier
• Un fichier ouvert à l’aide de la fonction fopen
doit être fermé on utilise ainsi la fonction
fclose
fclose (pointeurversmonfichier);
3.8.3 Exemples
• <?
// ouverture sur un serveur ftp
$fp = fopen("ftp://login:mdp@nom_du_serveur_ftp/nom_du_fichier", "w");
// ouverture sur un serveur http
$fp = fopen("http://www.perdu.com/","r");
// ouverture d'un fichier en local (sur le serveur);
$fp = fopen("/mon_rep/mon_fichier.txt","r");
fclose($fp );
?>
•
<?
$fp = fopen("c:\MonRepertoire\info.txt", "r");
?>
3.8.4 Lecture d’un fichier
<?
// ouverture du fichier en lecture
$fp = fopen ( "MonSuperFichier.txt" ," r " ) ;
// affichage du fichier
fpassthru($fp ) ;
fclose($fp );
?>
<?
// affichage du fichier
readfile(‘’MonSuperFichier.txt’’);
?>
3.8.5 Lecture d’un fichier ligne par ligne
• fgets() parcourt un fichier ligne par ligne
fgets(PointeurVersMonFichier[,longueur])
• fgets permet de lire une chaine dans un fichier
(pointeurVersMonFichier est initialisé à l’aide
de fopen) a partir de la position courante dont
la longueur est specifié par longueur.
3.8.6 Lecture d’un fichier ligne par ligne
• <?
// ouverture du fichier
$fp = fopen ("/mon_rep/mon_fichier.txt", "r");
while (!feof($fp )) {
$contenuFichier = fgets($fp);
// Ecrire à l'écran la chaîne lue
echo $contenuFichier;
}
fclose ($fp );
?>
3.8.7 Ecrire dans un fichier
• fwrite (PointeurDeFichier, ChaineAEcrire [, Longueur])
fputs() est un alias de fwrite -> fwrite()=fputs()
<?
/*
ouverture du fichier en mode lecture-écriture :
le pointeur est à la fin du fichier
*/
$fp =fopen('fichier.txt' , 'a+');
// écriture de la ligne
fwrite($fp ,"Nouvelle ligne à insérer \n");
// fermeture du fichier
fclose ($fp );
?>
3.8.7 se deplacer dans un fichier
• Pour revenir au debut du fichier : rewind()
Ex :
<?
$fichier= fopen(''superfichier.txt'',"r+");
$contenu= fgets($fichier,25);
rewind($fichier); // rewiiiiiiiiiiiiiiiiiiiiiiiiind
fclose($fichier);
?>
• Se deplacer dans un fichier fseek() fseek(PointeurDeFichier,position)
<?
$fichier= fopen(''superfichier.txt'',"r+");
$contenu= fgets($fichier,25);
fseek ($fichier,0); // rewiiiiiiiiiiiiiiiiiiiiiiiiind
fclose($fichier);
?>
•
3.8.9 Exemple : Ecrire un compteur en php
• Il suffit de stocker quelque part le nombre de visite dans
une base de donnée ou dans un fichier
• On aura besoin d’un fichier "compteur.txt" qui stockera la
valeur de notre compteur. On utilisera fwrite et fopen pour
ecrire ou lire dans le fichier
• Exemple : http://mastercaweb.u-strasbg.fr/bofh/
• Source :
http://mastercaweb.ustrasbg.fr/bofh/compteur.phps
3.8.10 Exemples : Ecrire un livre d'or
• Il suffit de stocker dans un fichier texte les contributions
de nos visiteurs
• On aura besoin d’un fichier "livredor.txt" qui stockera ce
que nos visiteurs posteront à l'aide d'un formulaire
• Exemple : http://mastercaweb.u-strasbg.fr/bofh/livredor/
• Source : http://mastercaweb.u-strasbg.fr/bofh/livredor/src/
4.0 Les sessions
• Les sessions est un moyen simple de conserver des variables sur
toutes les pages d ’un site.
• Jusqu'ici, on était arrivés à passer des variables de page en page
via la méthode GET (en modifiant l'url : page.php?
variable=valeur&variable2=valeur2) et via la méthode POST (=un
formulaire).
• Si on veut transmettre une ou plusieurs variables sur TOUTES les
pages de son site, ca devient ingérable avec GET et POST... D'où
l'invention des sessions.
4.0 Les sessions
• Un visiteur se connecte. On demande à créer une session pour lui :
PHP génère un identifiant unique pour ce visiteur du site.
• Pour cela, on utilise la fonction session_start(). L ’identifiant est une
chaine de caractères assez conséquente codée en hexadécimal.
• Ex : a02bbffc6198e6e0cc2715047bc3766f
• Ce numéro sert d'identifiant et est appelé "ID de session" (ou
PHPSESSID).
• PHP transmet automatiquement cet ID de page en page en utilisant
un cookie ou via l'url (ex : mapage.php?
PHPSESSID=a02bbffc6198e6e0cc2715047bc3766f).
4.0 Les sessions
• A partir de là on peut créer une infinité de variables de session. Par
exemple : $_SESSION['login'] contient le login du visiteur,
$_SESSION['password'] contient le mot de passe etc...
• L'avantage, c'est que le serveur conserve ces variables même
lorsque la page PHP a fini d'être générée.
• Quelque soit la page visitée, on peut récupérer par exemple le login
et le mot de passe du visiteur !
• Lorsque le visiteur se déconnecte (il a cliqué sur un bouton
"Déconnecter" ou est resté inactif trop longtemps), alors la session
est fermée avec la fonction session_destroy()
• Il ne faut jamais oublier d'appeler session_start() sur chacune
des pages AVANT d'écrire le moindre code HTML.
4.1 Utilité des sessions
• Un script qui demande un login / mot de passe pour qu'un visiteur
puisse se "connecter" (s'authentifier). Ainsi, on peut enregistrer des
variables de session et se souvenir du login du visiteur sur toutes
les pages du site !
• Ce qui permet d'ailleurs de créer une zone d'administration
sécurisée sur plusieurs fichiers SANS utiliser de .htaccess. Les
variables de sessions sont suffisantes pour vérifier si le mot de
passe est le bon.
• on se sert des sessions sur les sites de vente en ligne. Cela permet
de gérer un "panier" : on retient les produits que commande le
client, quelle que soit la page où il est. Lorsqu'il valide sa
commande, on récupère ces informations et on le fait payer…
4.2 Ecriture d'une variable de session
• On utilisera session_start() et la superglobale $_SESSION[]
<?php
// initialisation
session_start() ;
$_SESSION['IlEstCommentBofh'] = 'il est cool';
?>
4.3 Lecture d'une variable
<?php
// initialisation
session_start() ;
// tester la présence de la variable 'IlEstCommentBofh' dans la session
if ( isset( $_SESSION['IlEstCommentBofh'] ) ) {
echo 'IlEstCommentBofh a pour valeur ' ;
// lecture de la variable de session 'langage'
echo $_SESSION['IlEstCommentBofh'] ;
} else {
echo 'IlEstCommentBofh inconnu snif snif' ;
}
?>
4.4 Fin de session
<?php
// on initialise et utilise la session
session_start();
$_SESSION['IlEstCommentBofh'] = 'Il est cool';
echo $_SESSION['IlEstCommentBofh']; // affiche Il est cool
// php is alive il travaille
// on détruit la session
session_destroy();
unset($_SESSION);
$_SESSION['IlEstCommentBofh'] ; // n'affiche rien
?>
5.0 Les expressions régulières
• Les expressions régulières sont des modèles créés à
l'aide de caractères ASCII permettant de manipuler des
chaînes de caractères et de trouver les portions de la
chaîne correspondant au modèle.
• Ce système vient de POSIX (norme à l'origine sous Unix).
De nombreux scripts sous UNIX les utilisent.
• Les expressions régulières permettent de rechercher
des occurrences (= suite de caractères correspondant à
ce que l'on recherche) grâce à une série de caractères
spéciaux. L'expression régulière en elle-même est donc
une chaîne de caractère contenant des caractères
spéciaux et des caractères standards
5.1 Domaine d’application
• Vérifier la validité des chaînes de caractères ( saisie
dans un formulaire : email, entrée chiffrée, entrée
texte, etc...)
• Extraire des parties bien précises d'une chaîne, d'un
texte, d'une page...
• Modifier une date au format us (05-30-1977) au
format fr notamment (30/05/1977)
• Remplacer automatiquement toutes les adresses
"http://" par des liens cliquables (cf forums,
guestbook … )
• Pour créer son propre langage simplifié à partir de la
norme HTML, bbCode ([b][/b]...)
5.1 Champ d’application
• Il existe 2 types d'expressions régulières.
• POSIX : ( Portable Operating System Interface
plus le X d'UniX )c'est un langage d'expressions
régulières mis en avant par PHP
• PCRE : ( Perl Compatible Regular Expression )
:ces expressions régulières sont issues d'un autre
langage (le Perl) plus complexes, elles sont
surtout bien plus rapides et performantes.
5.2 Les fonctions utiles
• preg_grep , preg_split , preg_quote , preg_match ,
preg_match_all , preg_replace ,
preg_replace_callback
• Chaque fonction a sa particularité, certaines
permettent de faire simplement une recherche,
d'autre une recherche / remplacement, mais leur
gros point commun c'est qu'elles utilisent un
"langage" identique pour faire une recherche.
5.3 preg_match
<?
?>
if (preg_match("** REGEX **", "string’’))
{
echo 'Le mot que vous cherchez se trouve dans la chaîne';
}
else
{
echo 'Le mot que vous cherchez ne se trouve pas dans la chaîne';
}
!(((https?|ftp)://(w{3}\.)?)(?<\!www)(\w+-?)*\.([a-z]{2,6}))!
5.1 Faire des recherches sur les chaines
• une regex est toujours entourée de caractères
spéciaux appelés délimiteurs.
On peut choisir n'importe quel caractère
spécial comme délimiteur, dans les exemples
suivant on prendra par convention le
délimiteur « ! »
!Ma regex! /Ma regex/ 'Ma regex'
5.1 Faire des recherches sur les chaines
• Pourquoi des délimiteurs
‘’ !MA REGEX! ‘’
‘’ !MA REGEX!Options ‘’
• Exemple :
<?
if (preg_match("!ture!", ‘’la culture c’est comme la confiture…"))
{
echo 'VRAI';
}
else
{
echo 'FAUX';
}
?>
5.1 Faire des recherches sur les chaines
• Attention les regex sont
sensibles à la casse
• Pour ne pas faire la
différence majuscules /
minuscules on peut
ajouter une option à
notre regex
CHAINE
REGEX
RESULTAT
J’adore aller à
Londres
!Londres!
VRAI
J’adore aller à
Londres
!LONDRES!
FAUX
CHAINE
REGEX
RESULTAT
J’adore aller à
Londres
!Londres!i
VRAI
J’adore aller à
Londres
!LONDRES!i
VRAI
5.1 Faire des recherches sur les chaines
• La barre oblique « | » signifie « ou » dans les
regex :
CHAINE
REGEX
RESULTAT
J’adore aller à Londres
!Londres|Amsterdam!
VRAI
J’adore aller à
Muloose
!Londres|Amsterdam!
FAUX
5.1 faire des recherches dans des chaines
• Les regex permettent des recherches précises et très structurés,
dans les exemples précédant le mot pouvait se trouver n’importe ou
dans la chaîne
• ^ (accent circonflexe) : indique le début d'une chaîne.
• $ (dollar) : indique la fin d'un chaîne.
• Ainsi si on veut qu’un chaine commence par ‘’Yo’’ il faudra noter la
regex de cette manière :
!^Yo!
• De même, si on veut vérifier que le chaîne se termine par ‘’ ca gaze
", on écrira cette regex :
!ca gaze$!
5.1 faire des recherches dans des chaines
CHAINE
REGEX
RESULTAT
Yo Bob ca gaze
!^Yo!
VRAI
Yo Bob ca gaze
!ca gaze$!
VRAI
Yo Bob ca roule
!ca gaze$!
FAUX
5.2 Les classes de caractères.
• !gr[aio]s!
• Entre crochets = la classe de caractères.
Cela signifie qu'une des lettres à l'intérieur
peut convenir pour notre REGEX.
• Notre regex reconnaît donc gras gros et gris
5.2 Les classes de caractères
CHAINE
REGEX
RESULTAT
La nuit, tous les chats sont gris
!gr[aoi]s!
La nuit, tous les chats sont gros
!gr[aoi]s!
VRAI
VRAI
Soyez réaliste demander l’impossible
!^[aeiouy]!
Kawai
![aeiouy]$!
FAUX
VRAI
5.3 Les intervalles de classes
• Grâce au symbole "-" (le tiret), on peut autoriser toute une plage de
caractères.
Si on veut que la chaine contienne une lettre on écrira pas :
[abcdefghijklmnopqrstuvwxyz] on peut utiliser les intervalles.
• [a-z] ou [a-e] avec les chiffres : [0-9] , [1-8] …
• On peu combiner les plages aussi : [a-z0-9]. Cela signifie
"N'importe quelle lettre (minuscule) OU un chiffre".
On peut aussi autoriser les majuscules, sans passer par les options
: [a-zA-Z0-9].
[a-zA-Z0-9]
=[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]
5.3 Les classes de caractères.
CHAINE
REGEX
RESULTAT
Cette phrase contient une lettre
![a-z]!
VRAI
cette phrase ne comporte pas
de majuscule ni de chiffres
![a-z0-9]!
VRAI
Cette phrase commence pas
par un chiffre
!^[0-9]!
FAUX
<h1>Une balise de titre
HTML</h1>
!<h[1-6]>!
VRAI
5.3 Les classes de caractères
• Pour omettre un caractère dans une classe on utilise
aussi le symbole ‘^’
CHAINE
REGEX
RESULTAT
Cette phrase ne contient pas
de chiffre
![^0-9]!
VRAI
cette phrase ne comporte
pas de majuscule ni de
chiffre
![^A-Z0-9]!
VRAI
Cette phrase ne se termine
pas par une voyelle
![^aeiouy]$!
FAUX
Cette phrase ne commence
pas par une minuscule
!^[^a-z]!
VRAI
5.4 Les quantificateurs
• Les quantificateurs, ce sont des symboles qui permettent de dire
combien de fois peuvent se répéter un caractère, ou une suite de
caractères.
• ? (point d'interrogation) : ce symbole indique que la lettre est
facultative. Elle peut y être 0 ou 1 fois.
Ainsi, !a?! reconnaît 0 ou 1 "a".
• + (signe plus) : la lettre est obligatoire. Elle peut apparaître 1 ou
plusieurs fois.
Ainsi, !a+! reconnaît "a", "aa", "aaa", "aaaa" …
• * (étoile) : la lettre est facultative. Elle peut apparaître 0, 1 ou
plusieurs fois.
Ainsi, !a*! reconnaît "a", "aa", "aaa", "aaaa" etc... Comme c’est
facultatif si a n’y est pas ça renvoi vrai aussi !!!
• Les quantificateurs s'appliquent à la lettre directement derrière. On
peut ainsi autoriser le mot ‘’disque" qu'il soit au singulier comme au
pluriel, avec la regex !disques?!
5.4 Les quantificateurs
• Pour répéter plusieurs lettres on peut utiliser
les parenthèses :
• !Prout(prout)*! : reconnaitra
Proutproutproutprout …
5.4 Les quantificateurs
CHAINE
REGEX
RESULTAT
aaaaa
!a+!
VRAI
bbbb
!c?!
VRAI
Prouuuuuuuuuuut
!^Prou+t!
VRAI
Blablablablabla
!^Bla(bla)*$!
VRAI
5.4 Les quantificateurs.
• ? correspond à {0,1}
• + correspond à {1,}
• * correspond à {0,}
5.5 Les métacaractères.
• « Ce sont des caractères pas comme les
autres qui servent normalement à faire
quelque chose de particulier. »
• En PCRE (des Regex), les métacaractères
qu'il faut connaître sont les suivants :
!^$()[]{}?+*.\
5.5 Les métacaractères : les termes reservés
• "!" (point d'exclamation) : il sert toujours à indiquer la fin de
la Regex. Si on cherche ‘’kestumedis !? ’’ La regex sera :
! kestumedis \!\?!
• "]" (crochet fermant) : normalement, le crochet fermant
indique la fin de la classe il faut là aussi mettre un antislash
devant si on veut l’utiliser dans une regex.
• "-" (tiret) : Le tiret sert à définir un intervalle de classe
(comme [a-z]).
[a-z0-9-] permet de chercher une lettre, un chiffre, ou un
tiret.
5.5.2 Exemples :
•
•
On va tester la saisie d’une adresse email dans un
formulaire.
Les regles pour une adresse email valide :
–
–
–
–
On a tout d'abord le pseudonyme (au minimum une lettre). Il
peut y avoir des lettres minuscules (pas de majuscules), des
chiffres, des points, des tirets et des underscores "_".
Il y a ensuite une arobase : @
Ensuite il y a le nom du fournisseur d'accès. Pour ce nom, que
des minuscles, des chiffres, des tirets, des points et des
underscores.
Enfin, il y a l'extension (comme ".fr"). Cette extension
comporte un point, suivi de 2 à 6 lettres (minuscules).
5.5.2 Valider une adresse email
• !^$! Tout d’abord une fin et un début de chaine
• Ensuite, on a des lettres, chiffres, tirets, points, underscores, au
moins une fois. On utilise donc la classe [a-z0-9._-] à la suite de
laquelle on rajoute le signe + :
!^[a-z0-9._-]+$!
• l'arobase : !^[a-z0-9._-]+@$!
• Puis, encore une suite de lettres, chiffres, points, tirets au moins 2
fois : !^[a-z0-9._-]+@[a-z0-9._-]{2,}$!
• Pour le point de .fr .com … : !^[a-z0-9._-]+@[a-z0-9._-]{2,}\.$!
• Enfin l’extension (en minuscules) :
!^[a-z0-9._-]+@[a-z0-9._-]{2,}\.[a-z]{2,6}$!
5.5.2 Valider une adresse email
<?
if (isset($_POST['mail']))
{
if (preg_match("!^[a-z0-9._-]+@[a-z0-9._-]{2,}\.[a-z]{2,6}$!", $_POST['mail']))
{
echo 'L\'adresse ' . $_POST['mail'] . ' est <strong>valide</strong> !';
}
else
{
echo 'L\'adresse ' . $_POST['mail'] . ' n\'est pas valide, recommencez !';
}
}
?>
<form method="post">
<p>
<label for="mail">Votre mail ?</label>
<input id="mail" name="mail" /><br />
<input type="submit" value="Vérifier le mail" />
</p>
</form>
5.5.3 les autres classes génériques
\d tout caractère décimal [0-9]
\D tout caractère qui n'est pas un caractère décimal [^0-9]
\t Indique une tabulation
\n Indique une nouvelle ligne
\r Indique un retour chariot
\s tout caractère blanc ( \n \r \t )
\S tout caractère qui n'est pas un caractère blanc
\w tout caractère de [A-Za-z0-9_] plus les accentués
\W tout caractère qui n'est pas un caractère [^A-Za-z0-9_]
. tout caractère sauf \n
5.6 Captures et remplacement de chaines.
• Les expressions regulieres permettent de faire des recherches très
puissantes dans les chaines de caractères mais elle permettent
aussi d ’effectuer des rechercher / remplacer
• par exemple on pourra chercher s'il y a des adresses e-mail dans
un message laissé par un visiteur et modifier automatiquement son
message pour mettre un lien <a href="mailto:[email protected]">
devant chaque adresse, ce qui rendra les e-mails cliquables !
• On pourra ainsi rendre les liens http:// automatiquement cliquables
eux aussi ou bien créer notre propre langage simplifié pour le
visiteur, comme le fameux bbCode utilisé sur la plupart des forums.
5.6.1 Les parenthèses capturantes
• Pour l ’instant on se servait des parenthèses pour répéter des
éléments que l ’on veut chercher.
• On va se servir de la fonction preg_replace pour substituer des
chaines.
• preg_replace($Modele, $chaine_a_remplacer, $chaine);
• C'est avec cette fonction que nous allons pouvoir réaliser ce qu'on
appelle une "capture" de chaîne.
• Chaque fois qu ’on utilisera des parenthèses, ça va créer une
"variable" contenant ce qu'elles entourent.
5.6.1 Les parenthèses capturantes
• Exemple : !\[b\](.+)\[/b\]!
• Les parenthèses ici sont inutiles dans le cas d ’une recherche
simple, mais pour faire du rechercher remplacer ca va être utile.
• A chaque parenthèse ouverte dans une regex, php va créer une
variable appelée $1 (pour la première parenthèse), $2 pour la
seconde etc…
• On va se servir ensuite de ces variables pour modifier la chaîne
(=faire un remplacement).
5.6.2 Mettre en gras du texte
<?
$texte = preg_replace('!\[b\](.+)\[/b\]!i', '<strong>$1</strong>', $texte);
?>
•
•
•
•
premier paramètre la Regex. Attention chaque parenthèse va créer une variable
($1, $2 etc...)
On ajoute l'option "i" pour que le code fonctionne aussi avec des majuscules ([B]
[/B])
Ensuite on indique le texte de remplacement : "<strong>$1</strong>"
Enfin, dernier paramètre, c'est le texte dans lequel on fait notre recherche /
remplacement.
5.7 Regles à respecter
•
•
•
•
•
•
•
Avec plusieurs parenthèses, pour savoir le numéro d'une parenthèse il suffit de
les compter dans l'ordre de gauche à droite.
exemple !(anti)co(nsti)(tu(tion)nelle)ment!
Il y a 4 parenthèses dans cette regex (donc $1, $2, $3 et $4). La parenthèse
numéro 3 ($3) contient "tutionnelle", et la parenthèse $4 contient "tion"
C ’est l'ordre dans lequel les parenthèses sont ouvertes qui est important.
Les regex sont limitées à 99 parenthèses capturantes dans une Regex $99 est
donc la valeur maximum.
Il faut savoir qu ’une variable $0 est toujours créée, elle contient toute la Regex.
Sur le même exemple que tout à l'heure : !(anti)co(nsti)(tu(tion)nelle)ment!
$0 contient "anticonstitutionnellement".
Pour ne pas qu ’une parenthèse soit capturante (=pour simplifier les comptes, ou
ou si la regex est très complexe), il faut qu'elle commence par un point
d'interrogation suivi d'un deux points ":" -> ? :
5.7 Regles à respecter
!(anti)co(?:nsti)(tu(tion)nelle)ment!
La seconde parenthèse n'est pas capturante !
Il ne nous reste que 3 variables (4 si on compte $0) :
1. $0 : anticonstitutionnellement
2. $1 : anti
3. $2 : tutionnelle
4. $3 : tion
5.8 Exemple concret du bbcode
• Nous allons réaliser ce qu'on appelle un parser (= "parseur").
• Le parser va servir à transformer le texte rédigé par un visiteur
(forum / chat / livre d ’or...), en un texte inoffensif mais qui accepte
aussi du bbCode !
[b][/b] : pour mettre du texte en gras.
•
[i][/i] : pour mettre du texte en italique.
•
[color=red][/color] : pour colorer le texte
•
• Nous ferons en sorte de remplacer aussi automatiquement les URL
(http://) par des liens cliquables.
5.8 Contraintes
• Nous verrons tout d ’abord le texte en gras et en italique
• cf code pour le gras pour le faire fonctionner on va ajouter des
options au regex :
– * i : pour accepter les majuscules comme les minuscules ([B] et [b]
– * s : pour que le "point" fonctionne aussi pour les retours à la ligne (pour que
le texte puisse être en gras sur plusieurs lignes)
– * U : le U majuscule est une option qui signifie "Ungreedy" ("pas gourmand").
"Ce texte est [b]important[/b], il faut me [b]comprendre[/b] ! ``
Sans l'option Ungreedy, la Regex aurait voulu mettre en gras tout ce qu'il y a
entre le premier [b] et le dernier [/b]
(c'est-à-dire "important[/b], il faut me [b]comprendre"),
•
En utilisant l'option "U", la Regex s'arrêtera au premier [/b].
5.8 exemple bbcode
<?
$texte = preg_replace('!\[b\](.+)\[/b\]!isU', '<strong>$1</strong>', $texte);
$texte = preg_replace('!\[i\](.+)\[/i\]!isU', '<i>$1</i>', $texte);
$texte = preg_replace('!\[color=(red|green|blue|yellow|purple|olive)\](.+)\[/color\]!isU',
'<span style="color=$1">$2</span>', $texte);
$texte = preg_replace('!http://[a-z0-9._/-]+!i', '<a href="$0">$0</a>', $texte);
?>
6.0 Images dynamiques en php avec GD
• GD est une librairie de fonctions permettant la création/manipulation
d'images « à la volée »
• Depuis php 4.3 une version de GD est intégrée au système de base.
• Attention avec GD > 1,3 la génération d'images GIF n'est plus possible ou
limitée mais le png remplacera avantageusement le GIF.
• Il faut impérativement vérifier que GD soit installée sur le serveur pour
pouvoir l'utiliser
(cf php.ini ou phpinfo(); )
• Si GD n'est pas installée : « Fatal error: Call to undefined function »
6.0 GD : premier test
Pour générer notre image : (image.php)
<?php
// on spécifie le type de document que l'on va créer (ici une image au format PNG
header ("Content-type: image/png");
// on dessine une image vide de 200 pixels sur 100
$image = @ImageCreate (200, 100) or die ("Erreur lors de la création de l'image");
// on applique une couleur de fond, les couleurs sont au format RVB
$couleur_fond = ImageColorAllocate ($image, 255, 0, 0); // 255 intensité de rouge à donf
// on dessine notre image PNG
ImagePng ($image);
?>
Un fichier html appelant notre script :
<html>
<head>
<title>Superbe demo GD</title>
</head>
<body>
<img src="image.php">
</body>
</html>
6.0 La librairie GD
• Lorsque l'on utilise du HTML on a pas besoin d'utiliser les entêtes HTML
par contre lorsque le résultat de notre script affiche une image il faut
changer l'entête de notre fichier de sortie.
header ("Content-type: image/png"); pour du png
header ("Content-type: image/jpg"); pour du jpeg
header("Content-type: image/gif"); //format gif
header("Content-type: image/bmp"); //format bmp
header("Content-type: image/xbm");
header("Content-type: application/x-shockwave-flash"); //animation flash
6.0 La librairie GD
<?php
if (isset($_POST['rouge']) && isset($_POST['vert']) && isset($_POST['bleu'])) {
header ("Content-type: image/png");
$image = @ImageCreate (200, 100) or die ("Erreur lors de la création de l'image");
$couleur_fond = ImageColorAllocate ($image, $_POST['rouge'], $_POST['vert'], $_POST['bleu']);
ImagePng($image);
}
else {
echo 'Remplissez tous les champs du formulaire !!!';
}
?>
<html>
<head>
<title>Demo surpuissante avec GD</title>
</head>
<body>
Sélectionner l'intensité des différentes teintes :<br />
<form action="image2.php" method="post">
Rouge ( 0 - 255) : <input type="text" name="rouge"><br />
Vert ( 0 - 255) : <input type="text" name="vert"><br />
Bleu ( 0 - 255) : <input type="text" name="bleu"><br />
<input type="submit" value="gd rends moi fort!!!">
</form>
</body>
</html>
6.0 La librairie GD : fonctions utiles
•
•
•
•
•
•
•
•
•
•
•
$image = ImageCreate ($largeur, $hauteur) // permet de créer une image (png).
$image = ImageCreateTrueColor ($largeur, $hauteur) // idem a ImageCreate mais pour les jpeg.
$couleur = ImageColorAllocate ($image, $rouge, $vert, $bleu) // definis une couleur avec les intensités
RGB ( Red Green Blue).
ImageEllipse ($image, $x, $y, $l, $h, $couleur) // Dessine dans l'image $image une ellipse en partant
du poit ($x,$y), de largeur $l, de hauteur $h et de couleur $couleur.
ImageFilledEllipse ($image, $x, $y, $l, $h, $couleurl) // Idem que ImageEllipse mais avec une ellipse
pleine.
ImageFill ($image, $x, $y, $couleur) // colorie dans l'image $image un carré avec une position $x sur $y
et de la couleur $couleur.
ImageLine ($image, $x1, $y1, $x2, $y2, $couleur) // trace une ligne entre $x1,$y1 et $x2,$y2 et de
couleur $couleur pour $image.
ImageRectangle ($image, $x1, $y1, $x2, $y2, $couleur) // trace dans $image un rectangle de coin
supérieur gauche ($x1, $y1) et de coin inférieur droit ($x2, $y2) de couleur $couleur.
ImageFilledRectangle ($image, $x1, $y1, $x2, $y2, $couleur) // idem a ImageRectangle mais le
rectangle sera plein.
ImageSetPixel ($image, $x, $y, $couleur) // trace un point de coordonnées $x,$y de couleur $couleur
dans l'image $image
ImageSetThickness ($image, $epaisseur) // regle l'épaisseur des lignes tracées par toutes les fonctions
de l'image $image
6.0 La librairie GD : fonctions utiles
•
•
•
•
•
•
•
•
•
•
ImageString ($image, $police, $x, $y, $chaine, $couleur) // Dessine dans $image la chaîne de caractère
$chaine à partir du point ($x,$y) avec la couleur $couleur et avec la taille de police de caractère $police
(compris entre 0 et 5)
ImageStringUp ($image, $police, $x, $y, $chaine, $couleur) // idem que ImageString mais texte vertical
$tableau_image = GetImageSize ($fichier) // a partir d'une image $fichier,renvoie un tableau contenant
les 4 éléments suivants: $tableau_image[0] = la largeur de l'image,$tableau_image[1] = hauteur de
l'image,$tableau_image[2] donnce le type de l'image,$tableau_image[3] donne une chaine de caractère
directement utilisatble dans <img>
ImageColorTransparent ($image, $couleur) // la couleur $couleur de l'image $image est définis comme
transparente attention uniquement pour les png et les gifs !!!
ImageCopy ($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_l, $src_h) // Copie une partie
rectangulaire de l'image $src_im dans l'image $dst_im. La partie à copier est délimitée par le point
($src_x, $src_y), la largeur $src_l et la hauteur $src_h. La copie est placée dans $dst_im à partir du
point ($dst_x, $dst_y)
ImageCopyResampled($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_l, $src_h) // idem que
ImageCopy mais effectue également un redimensionnement.
$image = ImageCreateFromJpeg ($fichier) // créer une image jpeg $image depuis $fichier.
$im = ImageCreateFromPng ($fichier) // créer une image png $image depuis $fichier.
$largeur = ImageSX ($image) // renvoie la largeur de l'image $image.
$hauteur = ImageSY ($im) // renvoie la hauteur de l'image $image.
6.1 Scripts utiles
Faire un copyright sur des images
http://mastercaweb.u-strasbg.fr/bofh/gd/copyleft/
Test de miniatures en php
http://mastercaweb.u-strasbg.fr/bofh/gd/
8. Generer des pdfs
• Plusieurs possibilités :
– La libraire integré à php libpdf :
http://www.pdflib.com/pdflib-cookbook/
– fpdf : http://www.fpdf.org
– Google est votre ami …
9. Upload de fichiers en PHP
• Pour faire de l'upload ( =envoi de fichier ) en php via un formulaire il faut
préciser l'encodage à utiliser à l'aide le l'attribut enctype et placer une
balise xhtml input type=file.
<form method="POST" action="up.php" enctype="multipart/form-data">
Fichier :
<input type="hidden" name="MAX_FILE_SIZE" value="666">
<input type="file" name="fichier_a_envoyer">
<input type="submit" name="envoyer" value="envoyer">
</form>
9. Upload de fichiers en PHP
• <input type="hidden" name="MAX_FILE_SIZE" value="valeurmax">
• MAX_FILE_SIZE = la taille maximale (en octet) acceptée du fichier par
PHP.
• Il permet d'informer l'utilisateur/utilisatrice que le fichier à envoyer est trop
conséquent avant l'envoi complet du fichier vers le serveur.
• Attention ceci n'est pas un CONTROLE ! Juste une valeur de test de
« confort » il est très facile de modifier cette valeur via un autre
formulaire/via un script/ou des outils divers.
• Le paramètre PHP (côté serveur) à propos de la taille maximale d'un fichier
téléchargé, ne peut, lui, être trompé et doit être mentionné pour des
questions de sécurité.
9. Upload de fichiers en PHP
• Comme pour $_POST / $_GET / $_SESSION php va renseigner un table
$_FILES avec les principales caractéristiques de notre fichier envoyé via
notre formulaire html de soumission :
– $_FILES['fichier_a_envoyer']['name'] son nom
– $_FILES['fichier_a_envoyer']['tmp_name'] son chemin temporaire
pendant l'envoi
– $_FILES['fichier_a_envoyer']['size'] la taille du fichier
– $_FILES['fichier_a_envoyer']['type''] son type
– $_FILES['fichier_a_envoyer']['error''] code d'erreur eventuel
9. Les codes d'erreurs.
UPLOAD_ERR_OK
Valeur : 0. Aucune erreur, le téléchargement est correct.
UPLOAD_ERR_INI_SIZE Valeur : 1. Le fichier téléchargé excède la taille de upload_max_filesize, configurée dans le php.ini.
UPLOAD_ERR_FORM_SIZE Valeur : 2. Le fichier téléchargé excède la taille de MAX_FILE_SIZE, qui a été spécifiée dans le formulaire
HTML.
UPLOAD_ERR_PARTIAL Valeur : 3. Le fichier n'a été que partiellement téléchargé.
UPLOAD_ERR_NO_FILE Valeur : 4. Aucun fichier n'a été téléchargé.
UPLOAD_ERR_NO_TMP_DIR Valeur : 6. Un dossier temporaire est manquant. Introduit en PHP 5.0.3.
UPLOAD_ERR_CANT_WRITE Valeur : 7. Échec de l'écriture du fichier sur le disque. Introduit en PHP 5.1.0.
UPLOAD_ERR_EXTENSION Valeur : 8. Une extension PHP a arrêté l'envoi de fichier. PHP ne propose aucun moyen de déterminer quelle
extension est en cause. L'examen du phpinfo() peut aider. Introduit en PHP 5.2.0.
9. Upload de fichiers en PHP
•
•
•
•
•
Pour envoyer le fichier via php on utilisera la fonction move_uploaded_file :
bool move_uploaded_file ( string $filename , string $destination )
move_uploaded_file s'assure que le fichier filename est un fichier téléchargé par HTTP POST. Si le
fichier est valide, il est déplacé jusqu'à destination.
Si le fichier existe déjà il sera ecrasé.
move_uploaded_file Retourne TRUE en cas de succès.Si filename est un fichier téléchargé, mais que
pour une raison quelconque, il ne peut être déplacé, rien ne se passe, et move_uploaded_file() retourne
FALSE.
Attention aux limites pour la taille du fichier configuré dans le php.ini dans certain cas il faut surcharger
ces paramètres à l'aide d'un .htaccess notamment dans un env. Apache :
php_value post_max_size 10M
php_value upload_max_filesize 10M
9. Upload de fichiers en PHP
<?php
/*
* Script à ne pas utiliser pourquoi ?
*/
if(isset($_FILES['fichier_a_envoyer']))
{
$dossier = 'repertoire_upload/';
$fichier = basename($_FILES['fichier_a_envoyer']['name']);
if(move_uploaded_file($_FILES['fichier_a_envoyer']['tmp_name'], $dossier . $fichier))
{
echo 'envoi effectué avec succès !';
}
else
{
echo ''grrrrrrrrrrrrrrrr echec de l'envoi !'';
}
}
?>
9. Upload de fichiers en PHP
Utiliser le script d'upload précèdent est très dangereux avant tout il faut verifier via php la taille le type
du fichier, son nom !
• Pour la taille :
$taille = filesize($_FILES[fichier_a_envoyer']['tmp_name']);
if($taille>100000)
{
$erreur = 'Le fichier est trop fat...';
}
•
• Pour le type de fichier :
$extensions = array('.png', '.gif', '.jpg', '.jpeg');
$extension = strstr($_FILES['fichier_a_envoyer']['name'], '.');
if(!in_array($extension, $extensions)) //Si l'extension n'est pas dans le tableau
{
$erreur = 'type de fichier interdit !!!!!!!!!!!';
}
9. Upload de fichiers en PHP
• Le nom du fichier :
$fichier = strtr($fichier,
'ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ',
'AAAAAACEEEEIIIIOOOOOUUUUYaaaaaaceeeeiiiioooooouuuuyy'); .
$fichier = preg_replace('/([^.a-z0-9]+)/i', '-', $fichier);
•
Le code complet ici : http://mastercaweb.u-strasbg.fr/bofh/upload/
10.0 Conseils
•
•
Écrire du code facile à lire : indenter son script
Indentation = utilisation des tabulations pour présenter le code afin de le rendre
plus lisible
switch($page){
case "liens":
$page_a_inclure = "liens";
$titre_section = "Les liens";
break;
case "cv":
$page_a_inclure = "cv";
$titre_section = "mon cv";
break;
}
$page_a_inclure =
$page_a_inclure.".htm";
?>
switch($page)
{
case "liens":
$page_a_inclure = "liens";
$titre_section = "Les liens";
break;
case "cv":
$page_a_inclure = "cv";
$titre_section = "mon cv";
break;
}
$page_a_inclure =
$page_a_inclure.".htm";
?>
10. Conseils
•
•
•
•
•
•
•
•
Bien nommer ses variables : pas d'accents,espaces,caractères spéciaux ( =
réservés )
Nommer de facon explicite ses variables :
– Plutot $motdepasse ou $mot_de_passe mais pas $mdp
– Bien préciser ce que contient la variable : $date_commande $login_visiteur
Bien nommer les scripts que l'on utilise :
– login_forum.php envoi_livredor.php etc...
Utilisation de conventions de nommage :
– CamelCase ( $UpperCamelCase) ou camelCase ($lowerCamelCase)
– Notation Hongroise ($strMaChaine )
Documenter le code ( utilisation des commentaires ! )
Prévoir un fichier de paramétrage de l'application ( include ''config.php'' ; )
Penser à la sécurité en écrivant le code ( tester les variables, vérifier les saisies
utilisateurs, appréhender l'environnement dans lequel on code ( conf php /
apache ... )
Écrire des fonctions ( réutilisable dans d'autres applications ... )
10. Conseils
•
Ne pas réécrire la roue : utilisation de librairies de code ou d'api.
•
Utilisation d'un système de gestion de version (vcs pour Version Control System)
•
Avantages d'un vcs :
– Historique du code (permet de revenir sur une version du code chaque
nouvelle version d'un fichier est appellée 'révision' et le n° de version est
incrémentée de 1
– Conserve une trace de chaque changements effectués
– Possibilité de travail mutualisé (modifs nommés par utilisateur/développeur)
– Fusion entre copie locale et distance et non pas écrasement de la copie locale
par la copie distante.
•
Un wiki est aussi un vcs sauf que ce ne sont pas des fichiers qui sont
historisés mais des champs de bases de données.
•
Les vcs les plus connus (svn – subversion,bazaar,mercurial,cvs
,visual SourceSafe - krosoft)
10. Conseils
•
•
•
•
Utilisation de frameworks chaudement recommandée !
Framework : « En programmation informatique, un framework est un kit de
composants logiciels structurels, qui servent à créer les fondations ainsi que les
grandes lignes de tout ou partie d'un logiciel (architecture). » (src : wikipédia)
Avantages :
– standardisation du code et du cycle de vie de l'application
(specs,dvt,maintenance,évolution)
– On gagne en fiabilité
– Gains de productivité
– Souvent « communauté active » autour d'un framework
Frameworks orientés php :
– PEAR
– Zend Framework
– Symfony
– Prado
– PhpMVC
– Copix
– CodeIgniter
– CakePHP
10. Conseils
•
•
•
•
Utilisation de frameworks chaudement recommandée !
Framework : « En programmation informatique, un framework est un kit de
composants logiciels structurels, qui servent à créer les fondations ainsi que les
grandes lignes de tout ou partie d'un logiciel (architecture). » (src : wikipédia)
Avantages :
– standardisation du code et du cycle de vie de l'application
(specs,dvt,maintenance,évolution)
– On gagne en fiabilité
– Gains de productivité
– Souvent « communauté active » autour d'un framework
Frameworks orientés php :
– PEAR
– Zend Framework
– Symfony
– Prado
– PhpMVC
– Copix
– CodeIgniter
– CakePHP
10 Php et la sécurité
• Php est un langage très courant, beaucoup utilisé on peut faire tout et
n'importe quoi en php.
• Php est utilisé un peu partout en développement d'applications web dans
des domaines tel que : Traitement de formulaires, gestion de fichiers,
exécution de commandes systèmes ( = commandes du serveur ) ,
interfaçage à des bases de données, fonctionnalités « réseaux »
( ouverture de connections à distance... )
• Le fait d'exécuter nos scripts sur un serveur et non pas simplement au
niveau du client ( = le navigateur ) induisent de protéger au maximum ses
scripts.
• Il ne faut pas sous estimer la sécurité durant toute la phase d'élaboration
du projet jusqu'à l'exploitation de l'application ( = phase de prod )
• Sécuriser ses scripts implique que le serveur est mis à jour
régulierement et correctement paramétré.
10 Php et la sécurité : les regles de base
• <mode parano>Ne jamais faire confiance aux données transmises par
l'utilisateur/trice</mode parano>
• Tester l'existence et la cohérence d'un script à inclure dans un autre script.
• Limiter le plus possible les permissions ( = droits ) des utilisateurs/trices
->trop de liberté tue la liberté !
• Basé uniquement le contrôle au niveau client est illusoire ( blocage du
javascript ... )
• Privilégier la méthode post à la méthode get
( les variables en clair dans l'url c'est bien mais pas top ! )
• Toujours embêter l'administrateur du serveur pour avoir une version à jour
de php / apache et des outils web.
• RTFM : http://fr.php.net/manual/fr/security.php
10 phpinfo()
• Phpinfo() est une fonction très utile pour le développeur ( info sur la config
= le fichier php.ini , paramétrages, environnement serveur, version des
logiciels ... )
• Il faut éviter de permettre l'affichage du script utilisant phpinfo() aux
utilisateurs/trices de notre application web.
• Phpinfo() renseigne sur des mécanismes « clés » de php , ces derniers
influent sur la façon d'interpréter du code php.
• Les directives contenues dans le fichier php.ini dictent le comportement du
langage, qui à son tour, autorise différents modes d’opération, en fonction
des besoins et de l’environnement de l’utilisateur.
• Le script exécutant la fonction phpinfo() est une mine d'or pour une
personne mal intentionnée qui viendrait « visiter » notre serveur web.
10 fichier php.ini
• safe_mode : ( safe_mode = on | off )
- de nombreuses fonctions sont limitées ou desactivées
http://www.php.net/manual/fr/features.safe-mode.functions.php
- une vérification stricte des permissions d'accès des fichiers est
faite sur les fonctions concernées.
- impossibilité d'utiliser l'upload de fichiers.
- les variables d'environnement sont protégées.
• safe_mode_exec_dir : ( safe_mode_exec_dir = /private_dir/ )
- autorise le répertoire indiqué à utiliser les fonctions
interdites/limitées.
10 fichier php.ini
• safe_mode_allowed_env_vars :
( safe_mode_allowed_env_vars = PHP_ )
- Seules les variables commençant par les préfixes explicités dans
cette directives peuvent être utilisées.
• disable_fonctions : ( disable_functions = FonctionPhp )
- Cette directive est indépendante du « safe mode » elle permet de
déterminer les fonctions à désactiver
ex : disable_functions = exec, system, mail
• open_basedir : ( open_basedir = /usr/home/ftpuser/ )
- Cette directive (indépendante du safe_mode) limite les permissions
d'accès aux seuls dossiers spécifiés ici.
10 fichier php.ini
• display_errors : (display_errors = on | off )
- Cette directive désactive l'affichage vers le navigateur des
messages d'erreur PHP.
• log_errors : (log_errors = on | off), cette directive permettra la
redirection des messages d'erreur vers les fichiers journaux (fichiers
log sous unix), dans les journaux d'évènements (win), ou dans des
fichiers spécifiés dans la directive error_log
• error_log : (error_log = /var/log/erreurs_php.log ) :
- Specifie le fichier dans lequel seront écrits les messages d'erreur.
• register_globals ( register_globals = on | off ) :
- Permet de rendre globales ou non les variables EGPCS
(Environment, Get, Post, Cookie, Session).
10 fichier php.ini
• allow_url_fopen : ( allow_url_fopen = on | off )
- Cette option permet de désactiver ou non toutes les fonctionnalités
relatives à la manipulation des fichiers distants.
• magic_quotes_gpc : ( magic_quotes_gpc = on | off )
- Cette directive permet d'échapper (par backslashes = \) les quotes,
double quotes, backslashes et caractère NULL des chaînes de
caractères issues des méthodes Get, Post et Cookies.
• magic_quotes_runtime : ( magic_quotes_runtime = on | off )
- directive qui permet egallement d'échapper les quotes, double
quotes, backslashes et caractère NULL, mais des chaînes de
caractères provenant d'une ressource externe (base de données... )
• file_uploads : ( file_uploads = on | off )
- Autorise l'upload de fichiers sur le serveur via un script PHP
10 : La faille include
• Il existe une littérature abondante sur le web concernant cette faille.
• Il faut éviter d'utiliser des variables quand on veut inclure des fichiers
dans un script :
include($mon_repertoire. ''fonctions.php'');
ou encore pire include($page);
• Si on est administrateur on peut mettre allow_url_fopen sur off dans
le php.ini
• Le mieux reste de tester l'existence du fichier sur le serveur ou alors
d'utiliser un switch et de prévoir un cas par défaut pour les valeurs de
$page non prévues.
• Le but de cette attaque est de faire exécuter en local sur le serveur
qui héberge le script à risque un autre script
hébergé sur un
autre site.
10 Exploitation des variables globales
• Comme pour la faille include il faut faire attention à nos variables un script
d'authentification de ce genre pose probleme :
<?php
if ($password == "supermotdepasse")
$login_ok = 1;
...
if ($login_ok == 1)
echo "Bienvenue dans l'interface d'administration";
?>
http://www.rogerfaitdanslaprogweb.com/login?login_ok=1 nous permettra de
nous connecter !!!!
10 Authentification
•
•
•
•
•
•
Pour un système d'authentification il ne faut pas stocker le mot de passe en clair !!
On va utiliser la technique du 'hash' appellé fonction de hachage.
Le hash : somme de contrôle, empreinte, hash, condensat, empreinte autrefois 'signature
numérique' mais terme trop confus.
Le hashage est une fonction de codage à sens unique : il est impossible (en principe) de
retrouver un mot de passe à partir de son hash.
L'algorithme de hashage le plus courant en PHP s'appelle le MD5 (128 bits), mais on parle
aussi de SHA1 (160 bits) SHA-256, Whirlpool …
Pour stocker le mdp : $password = md5($_POST['password']);
$sql = "INSERT INTO users VALUES (..., '$password', ...)";
// pour le login
$username = addslashes($_POST['username']);
$password = md5($_POST['password']);
$sql = "SELECT username FROM users WHERE username = '$username' AND password =
'$password'";
[...] // on recupère dans $resultat le nb d'enregistrements renvoyé dans la requete
if ($resultat == 1) {
$login_ok = true;
} else {
$login_ok = false;
}
10 La faille XSS
• Le Cross site scripting, ( = XSS ) est une faille de sécurité courante dans
les applications Web, l'astuce consiste bien souvent à injecter du javascript
dans un formulaire de saisie, dans une variable php
• L'exploitation d'une faille de type XSS peut permettre à un intrus de réaliser
les opérations suivantes :
-Affichage d'un contenu non interne au site (publicité, faux article)
-Redirection (parfois de manière transparente) de l'utilisateur.
-Vol d'informations, par exemple sessions et cookies.
-Actions sur le site faillible, à l'insu de la victime et sous son identité
(envois de messages, suppression de données, etc.)
• Une faille de type XSS est à l'origine de la propagation des virus Samy (
http://namb.la/popular/tech.html ) sur MySpace en 2005 ainsi que de
Yamanner sur Yahoo!Mail en 2006.
10 La faille XSS
• Le meilleur moyen pour eviter la faille XSS : tester les saisies utilisateurs
→ <script type="text/javascript">alert('bouh la vilaine faille')</script>
• Pour contrer utiliser la fonction htmlentities() de php :
<?php
if(isset($_POST['message']))
{
echo htmlentities($_POST['message']);
}
?>
10 La faille XSS
• Autre technique utile pour annihiler le XSS :
$input = str_replace(''<'', ''&lt;'', $input);
$input = str_replace(''>'', ''&gt;'', $input);
$input = str_replace(''script'', '''', $input);
10 Faire mumuse avec mail()
• La fonction mail() interesse énormément les
''spammeurs'' !
• Mailbombeur :
<?
$to = "[email protected]";
$subject = "fear!!!!";
$message = "prout ";
for($i=0; $i<5000; $i++) {
mail($to, $subject, $message);
}
?>
10 Injection d'entètes dans mail()
mail([DESTINATAIRE],[SUJET],[MESSAGE],[HEADERS]);
Dans le cas d'un formulaire de soumission de mail ( page contact d'un site ) si les champs
ne sont pas filtrés/contrôlés on peut ajouter très facillement des entetes.
<? $to="[email protected]";
if (!isset($_POST["send"])){?>
<form method="POST" action="">
A: [email protected]<br>
De: <input type="text" name="expediteur"><br>
Sujet : <input type="text" name="sujet"><br>
Message : <br><br>
<textarea name="message" rows="10" cols="60" lines="20"></textarea><br>
<input type="submit" name="send" value="Envoyer">
</form><?
}else{
$from=$_POST["expediteur"];
if (mail($to,$_POST["sujet"],$_POST["message"],"From: $from\n")){
echo "Votre mail a bien été envoyé à $to.<br>";
}else{
// sinon, message d'erreur.
echo "Votre mail n\'a pas pu être envoyé.<br>";
}
•
•
10 Injection d'entètes dans mail()
Quand on enverra le formulaire :
To: $destinataire
Subject: $sujet
$headers
$message
Le but de l'attaque par injections d'headers ( = entetes ... ) est d'inseré des
entetes ( BCC,CC ... )
To: [email protected]
Subject: Haxor
From: [email protected]
Cc:[email protected]
Bcc:[email protected],[email protected]
My Message...
10 Injection d'entètes dans mail()
• Chaque entetes est separé par un retour à la ligne, il suffit de manipuler les
variables de notre script.
• Dans le champs expediteur :
• ''[email protected]%0ACc:[email protected]
%0ABcc:[email protected],[email protected]''
• %0A nous permets de signifier un retour à la ligne ( code hexadecimal )
• On aura donc :
To: [email protected]
Subject: prout
From: [email protected]
Cc:[email protected]
Bcc:[email protected],[email protected]
My Message...
10 Injection d'entètes dans mail()
• Il est tout a fait possible d'avoir deux fois l'entete « to; » dans un email :
• Dans le champs expediteur de notre formulaire : "[email protected]
%0ATo:[email protected]"
• Toujours dans notre exemple :
To: [email protected]
Subject: prout
From: [email protected]
To:[email protected]
My Message...
10 Injection d'entètes dans mail()
• Pour des formulaires de type « recommander ce site à un ami »
<?
$sujet="Visitez http://www.website.com !";
$message="Bonjour,\nUn ami vous conseille de visiter http://www.website.com.\n";
if (!isset($_POST["send"])){
?>
<form method="POST" action="">
A : <input type="text" name="destinataire"><br>
De: <input type="text" name="expediteur"><br>
<input type="submit" name="send" value="Envoyer">
</form>
<?
}else{
$from=$_POST["expediteur"];
$to=$_POST["destinataire"];
if (mail($to,$sujet,$message,"From: $from\n")){
echo "Votre mail a bien été envoyé à $to.<br>";
}else{
echo "Votre mail n\'a pas pu être envoyé.<br>";
}}?>
10 Injection d'entètes dans mail()
• if (eregi("\r",$from) || eregi("\n",$from)){
die("stupid guy !!!");
}
• La fonction eregi recherche les caractères de
retour à la ligne, il faut tester ceci avant de
forger les entetes finaux dans le script php de
validation du formulaire.
10 Injection « SQL »
• MySQL est un SGBD facile à utiliser, la plupart des scripts PHP utilisent
MySQL pour gérer leurs données.
• Imaginons un script du genre :
[ ... ]
$table ="contacts":
$query = "INSERT INTO $table ('$nom', '$email')";
$result = mysql_query($query);
[ ... ]
• MySQL est aussi capable d'effectuer deux requetes simultanées :
$query = "INSERT INTO contacts ('bofh', '[email protected]'); INSERT
INTO contacts ('bill', '[email protected]')";
$result = mysql_query($query);
10 Injection « SQL »
• Imaginons notre script avec un formulaire de
soumission
[ NOM ] bofh
[ MAIL ] '[email protected]'); INSERT INTO
contacts ('bill','[email protected]')
[ NOM ] bofh
[ MAIL ] '[email protected]'); DROP TABLE
contacts
10 Injection « SQL »
•Solution : il suffit d'utiliser la fonction addslashes(), qui ajoutera un backslash
'\' devant les caracteres posant problème : quote ("), apostrophe (') et
backslash(\).
$nom = addslashes($nom);
$email = addslashes($email);
$query = "INSERT INTO $table ('$nom', '$email');
Ou
$query = "INSERT INTO $table ('''.addslashes($nom).''',
'''.addslashes($email).''')'';
11. Les frameworks de dvt web.
Un framework web ?
Wikipedia : « En programmation informatique, un framework est un kit de composants
logiciels structurels, qui servent à créer les fondations ainsi que les grandes lignes de
tout ou d’une partie d'un logiciel (architecture). »
Framework : cadre pour coder proprement via un ensemble de bonnes pratiques
Ne pas ré-inventer la roue (DRY : « Don't Repeat Yourself »)
Boîte à outils/composants logiciels génériques
Rapidité et qualité du développement
Structuration du développement (Architecture Modèle/Vue/Contrôleur )
Des fonctionnalités par défaut pour le développement web
Le Design Pattern
Design pattern = patron de conception
« un arrangement caractéristique de modules, reconnu comme bonne
pratique en réponse à un problème de conception d'un logiciel. Il décrit une
solution standard, utilisable dans la conception de différents logiciels »
Mvc est un « design pattern »
Le Modèle MVC
Le Modèle de données : abstraction de la base de
données, en charge de l'accès et des requêtes
La Vue : présentation des données (HTML, XML,
JSON, RSS)
Le Contrôleur : implémentation de la logique métier,
liant entre le Modèle et la Vue
Le modèle MVC
Modèle de données
ORM
Couche d'abstraction Objet-Relationnel
Génération automatique de la base de
donnée
Une classe objet, une table de la base de
données avec :
-Les types de données
-Les contraintes d'intégrité
-Les relations entre les classes et leur
cardinalité (ex : relation 1-n)
L'ORM
L'ORM fournit des instructions de hautniveau pour la manipulation des objets.
Abstraction complète du SQL
Utilisation de CRUD pour la persistance des
données (Create, Read, Update, Delete)
Evite d'avoir à coder les accès à la base de
données l'ORM le fait pour nous (trop cool!)
Les vues (=views/templates)
Système de « template » Web :
Variables interprétées dynamiquement
Utilisation des instructions d'itération et de
condition des langages de programmation
Possibilité aussi de présenter des vues sous
différents formats : JSON, XML, RSS, PDF.
Gestion des URL
Systeme de « routage » :
Correspondance d’une URL à une methode ou
action d'un controleur
Base sur des expressions regulieres
Le controlleur
Decoupage du controleur en methodes (ou actions)
Liant entre le modele et la vue en fonction des
événements
Connaissance du contexte HTTP (environnement,
session, etc.)
Des fonctionnalités supplémentaires...
Conclusion
Utilisation des frameworks chaudement recommandée
Code propre facile à maintenir et à reprendre
Attention néanmoins aux frameworks exotiques et jeunes (peu de doc, peu
de retour d’expérience..)
Il faut suivre les bonnes pratiques de dev. , normalisation du code, tests
unitaires...
Inconvénients : chemin long et difficile jusqu'à la maitrise du framework
mais montée en compétence évidente.
La programmation objet (poo)
• Au début de l'informatique programmation procédurale voir séquentielle
• Prog séquentielle : l'execution du code est toujours le même en générale
ligne / ligne
• Une procédure (routine,sous routine,fonction) contient un nombre d'étape
(bloc de code ou instructions à suivre) à réaliser.
• Limite de la prog. Procédurale : un programme peut vite devenir compliqué
et on sait plus trop ce que fait le code => code spaghetti
10 i = 0
20 i = 1 + 1
30 IF i <> 10 then goto 70
40 IF i = 10 the goto 50
50 PRINT ''SUPER CODE''
60 END
70 PRINT '' HELLO''
80 GOTO 20
La programmation objet (poo)
• En programmation objet tout est OBJET
• Un objet = structure de données
• Un objet regroupe non seulement les données mais egallement les mouens
de traitement de ces données.
• Un objet est définis par des propriétés qui étendent l'objet et par des
méthodes qui servent à traiter les propriétés de l'objet.
• D'ou viennent les objets ? Ils sont definis par des « constructeurs »
appelés « classes »
• Une classe regroupe des variables et des fonctions (propriétés et
méthodes)
• Chacune des fonction dans une classe aura accès aux variables de cette
entité.
Déclaration et utilisation d'une classe.
• Il s'agit d'un bloc dont l'en-tête (=la signature) commence par le mot-clé
class.
• Extends est optionnel et annonce que la présente classe hérite (on parle de
sous-classe) des propriétés / méthodes d'une autre classe
class NomClasse [extends ClasseParent] {
// déclarations des attributs (ou propriétés)
...
// déclarations du constructeur et des méthodes
...
}
• Par convention de nommage les noms de classe commencent par une
majuscules mais ce n'est pas obligatoire !
Poo : concepts de base
• Instance de classe : instancier une classe c'est se servir d'une classe pour
créer un objet.
• Une classe réunie dans la même entité les données et les moyens de les
gérer (les champs et les méthodes) c'est l'encapsulation
• en interdisant la modif. directement des attributs, et en obligeant
l'utilisation des fonctions définies pour les modifier (appelées interfaces), ce
principe assure l'intégrité des données manipulés.
• Il existe trois niveaux de visibilité pour une classe :
– Publique : les fonctions de toutes les classes peuvent accéder aux
données ou aux méthodes d'une classe définie avec le niveau de
visibilité public. Il s'agit du plus bas niveau de protection des données
– Protegée : l'accès aux données est réservé aux fonctions des classes
héritières, c'est-à-dire par les fonctions membres de la classe ainsi que
des classes dérivées.
– privée: l'accès aux données est limité aux méthodes de la classe ellemême. Il s'agit du niveau de protection des données le plus élevé
Les attributs des objets
• Les attributs d'objets = les variables de la classe.
• En php 4 Ils sont obligatoirement introduit par le mot-clé var
Ex : var $attribut = valeur ;
En php 5 public|private|protected $attribut = valeur ;
• Le type de la variable est quelconque : entier, double, chaine
ou tableau
• L'accès des (futurs) objets à la valeur d'un attribut utilise la
syntaxe suivante : $objet -> attribut;
• Attention pas de $ devant le nom de l'attribut !!!
L'accès aux membres d'une classe.
// ClasseQuiTueTout.php
class ClasseQuiTueTout {
public $variablePublic = "variable 'public'";
private $variablePrivate = "variable 'private'";
protected $variableProtected = "variable 'protected'";
// Notre constructeur qui tue tout !!!!
function __construct(){}
}
Les membres public d'une classe sont accessibles partout :
$demoQuiTueTout = new ClasseQuiTueTout();
echo $demoQuiTueTout->variablePublic;
// Renvois variable 'public'
L'accès aux membres d'une classe.
// ClasseQuiTueTout.php
class ClasseQuiTueTout {
public $variablePublic = "variable 'public'";
private $variablePrivate = "variable 'private'";
protected $variableProtected = "variable 'protected'";
// Notre constructeur qui tue tout !!!!
function __construct(){}
}
Les membres public d'une classe sont accessibles partout :
$demoQuiTueTout = new ClasseQuiTueTout();
echo $demoQuiTueTout->variablePrivate;
// Renvois une erreur fatale (game over!!!!)
// Fatal error: Cannot access private property ClasseQuiTueTout::$variablePrivate
in /cheminDuScript/code_roxor.php on line xx
L'accès aux membres d'une classe.
// ClasseQuiTueTout.php
class ClasseQuiTueTout {
public $variablePublic = "variable 'public'";
private $variablePrivate = "variable 'private'";
protected $variableProtected = "variable 'protected'";
// Notre constructeur qui tue tout !!!!
function __construct(){}
// methode pour retourner notre variable privé
function getVariablePrivate(){
return htmlentities($this->variablePrivate);
}
}
Ensuite :
$demoQuiTue = new ClasseQuiTueTout();
echo $demoQuiTue->getVariablePrivate();
L'accès aux membres d'une classe.
// ClasseQuiTueTout.php
class ClasseQuiTueTout {
public $variablePublic = "variable 'public'";
private $variablePrivate = "variable 'private'";
protected $variableProtected = "variable 'protected'";
// Notre constructeur qui tue tout !!!!
function __construct(){}
// methode pour retourner notre variable privé
function getVariablePrivate(){
return htmlentities($this->variablePrivate);
}
}
class SousClasseQuiTache extends ClasseQuiTueTout {
function __construct(){}
function accesPrivate(){
echo $this->variablePrivate;
}
function accesProtected(){
echo $this->variableProtected;
}
}
$demo = new SousClasseQuiTache();
echo $demo->accesProtected();
// Affiche variable 'protected'
echo $demo->accesPrivate();
// Erreur d'accès
Exemple de classe
// la classe ''Personne''
class Personne {
public $nom;
public $prenom
public $type;
...
} // fin classe
$personne = new Personne;
// on affecte une valeur à ses attributs $prenom et $type
$personne -> prenom = "luke";
$personne -> type = 'jedi';
Création de méthodes
class Personne {
private $nom;
private $prenom;
private $type;
…
Public function seServirDeLaForce() // se servir de la force et tout casser
{
...
}
Public function attaquerEtoileNoire() // on va casser du méchant
{
...
}
}
Utilisation de $this
•
•
La variable $this represente l'objet créé par la classe.
En appellant $this on pourra appeler les methodes de notre objet ou modifier ses attributs.
class Personne {
private $nom, $type, $vaisseau, $force, $degats, $experience ;
…
public function domages($force)
{
$this->degats = $this->degats+$force
}
public function attaquer($perso)
{
$perso ->domages($this->force)
}
public function gagnerExperience()
{
$this->experience++;
}
Les accesseurs
Pour pouvoir utiliser notre classe de tout à l'heure il va falloir definir la force et l’expérience
de nos heros on va se servir des accesseurs et des mutateurs.
class Classe {
private $attribut;
public function Classe(){
$this->attribut = null;
}
//Accesseur
public function getAttribut(){
return $this->attribut;
}
//Mutateur
public function setAttribut($valeur){
$this->attribut = $valeur;
}
}
$objet = new Classe(); //Instanciation d'une classe
$objet->setAttribut(10);
echo $objet->getAttribut();
•
Classe personne
class Personne {
private $nom, $type, $vaisseau, $force, $degats, $xp ;
…
public function setForce ($force)
{
if (!is_int ($force)) // S'il ne s'agit pas d'un nombre entier
{
trigger_error('La force d\'un personnage doit être un nombre entier', E_USER_WARNING);
return;
}
if ($force > 100) // On vérifie bien qu'on ne souhaite pas assigner une valeur supérieure à 100
{
trigger_error('La force d\'un personnage ne peut dépasser 100', E_USER_WARNING);
return;
}
$this->force = $force;
}
...
Classe personne
...
public function degats()
{
return $this->degats;
}
public function force()
{
return $this->force;
}
public function experience()
{
return $this->experience;
}
}
Classe personne
…
public function setExperience ($experience)
{
if (!is_int ($experience)) // S'il ne s'agit pas d'un nombre entier
{
trigger_error('L\'expérience d\'un personnage doit être un nombre entier', E_USER_WARNING);
return;
}
if ($experience > 100) // On vérifie bien qu'on ne souhaite pas assigner une valeur supérieure à 100
{
trigger_error('L\'expérience d\'un personnage ne peut dépasser 100', E_USER_WARNING);
return;
}
$this->experience = $experience;
}
Classe personne
<?php
$perso1 = new Personnage(); // Un premier personnage
$perso2 = new Personnage(); // Un second personnage
$perso1->setForce (10);
$perso1->setExperience (2);
$perso2->setForce (90);
$perso2->setExperience (58);
$perso1->frapper ($perso2); // $perso1 frappe $perso2
$perso1->gagnerExperience(); // $perso1 gagne de l'expérience
$perso2->frapper ($perso1); // $perso2 frappe $perso1
$perso2->gagnerExperience(); // $perso2 gagne de l'expérience
echo 'Le personnage 1 a ', $perso1->force(), ' de force, contrairement au deuxième
personnage qui a ', $perso2->force(), ' de force.<br />';
echo 'Le personnage 1 a ', $perso1->experience(), ' d\'expérience, contrairement au
deuxième personnage qui a ', $perso2->experience(), ' d\'expérience.<br />';
echo 'Le personnage 1 a ', $perso1->degats(), ' de dégâts, contrairement au deuxième
personnage qui a ', $perso2->degats(), ' de dégâts.<br />';
?>
Le constructeur
• Le constructeur est la fonction qui est appelée automatiquement par la
classe lors de l'instanciation de la classe à l'aide de l'opérateur new.
• La fonction constructeur a le même nom que la classe en php4 pour php5 :
__construct()
• Une fonction/methode devient le constructeur si elle porte le même nom
que la classe (php < php5)
class BaseClass {
function __construct() {
print "In BaseClass constructor\n";
}
}
class SubClass extends BaseClass {
function __construct() {
parent::__construct();
print "In SubClass constructor\n";
}
}
$obj = new BaseClass();
$obj = new SubClass();
Le constructeur
<?php
class Personnage
{
private $force;
private $localisation;
private $experience;
private $degats;
public function __construct ($force, $degats) // Constructeur demandant 2 paramètres.
{
echo 'Aller ca construit !'; // Message s'affichant une fois que tout objet est créé.
$this->force = $force; // Initialisation de la force.
$this->degats = $degats; // Initialisation des dégâts.
$this->experience = 1; // Initialisation de l'expérience à 1.
}
// …. methodes ...
}
?>
<?php
$perso1 = new Personnage (60, 0); // 60 de force, 0 dégât.
$perso2 = new Personnage (100, 10); // 100 de force, 10 dégâts.
?>
Exemple de connection Mysql
class Connexion
{
private $server, $user, $password, $database;
public function __construct ($server, $user, $password, $database)
{
$this->server = $server;
$this->utilisat = $user;
$this->password = $password;
$this->database = $database;
$this->connDb();
}
private function connDb()
{
mysql_connect ($this->server, $this->user, $this->password);
mysql_select_db ($this->database);
}
}
Fichier appelant notre classe :
<?php
$connexion = new Connexion ('localhost', 'root', 'gotroot?', 'allyourbase');
?>
Comment appeler nos classes ?
<?php
function chargerClasse ($classe)
{
require $classe . '.class.php'; // inclusion de la classe
}
$perso = new Personne(); // Instanciation de la classe Personne qui n'est pas déclarée dans ce fichier
?>
→ renvois une erreur fatale il faut utiliser l'autoload de php :
<?php
function chargerClasse ($classe)
{
require $classe . '.class.php'; // On inclue la classe correspondante au paramètre passé
}
spl_autoload_register ('chargerClasse');
$perso = new Personne();
?
Charger nos classes
Depuis php v5.3 :
<?php
function __autoload($class_name) {
include $class_name . '.php';
}
$obj = new MaClasse1();
$obj2 = new MaClasse2();
?>
Utiliser un ORM
•
Cf wikitruc : « Un mapping objet-relationnel (en anglais object-relational mapping ou ORM) est une
technique de programmation informatique qui crée l'illusion d'une base de données orientée objet à
partir d'une base de données relationnelle en définissant des correspondances entre cette base de
données et les objets du langage utilisé. On pourrait le désigner par « correspondance entre monde
objet et monde relationnel »
Utiliser un ORM
•
•
•
•
•
Un ORM est votre ami : il permet d’accroître fortement la productivité au cours d'un dev. lié à des bases
de données.
Couramment utilisés dans de nombreux frameworks web : Symfony,Zend, et pas seulement en php,
en .NET avec notamment NHibernate, Hibernate en Java, Django et SQLAlchemy en python.
Souvent utiliser avec le design pattern MVC
Avantages :
– Si on maîtrise → génération de requêtes SQL plus stables, plus sécurisées et performantes
– Gestion et prise en charge des accès à la base de données par l'ORM
– Évolution et maintenabilité avec la possibilité de migrer rapidement vers un autre SGBD.
Limites :
– Performances sur des grosses bases.
– Connaissances en POO obligatoires.
– Gestion des relations 1 à n / n à n , verrous pas toujours simples à comprendre.
– Utilisation mémoire importante.
Utiliser un ORM
ORM pour PHP
•
•
•
•
•
•
PersistentObject : fait partie du projet eZ Components surtout connu pour eZ Publish (->CMS)
Propel : projet plus ou moins maintenu actuellement ; beaucoup utilisé par la communauté Symfony à
ses débuts (v1) , critique sur certains concepts qui éloigne Propel de la syntaxe SQL de base.
PhpSimpleDB : ORM jeune, projet francophone, concept déroutant on commence par écrire nos
requêtes sql et l'ORM va generer à la volée à la première execution les classes associées au modèle.
PdoMap : bibliothèque greffée à l'extension php PDO (phpDataObjects) PDO est une couche
d'abstraction entre le serveur executant le code php et la base de données. PdoMap encapsule les
entités d'une base de données sous la forme d'objet. PDO quant à lui gêre la connexion et le requettage
AGILE TOOLKIT ORM : approche plus minimaliste que certains autres ORMs
Doctrine : ORM en vogue, notamment dans Symfony 1.x et Symfony 2, assez complexe, beaucoup de
fonctionnalités. Grande force son DQL (=Doctrine Query Language) : le langage de requêtage inspiré
de Hibernate et son HQL (ORM Java) problèmes de performance sur des grosses bases (doctrine est
gourmand en ressources) Doctrine 2 est à suivre de prêt !
Il y a bien longtemps :
<?php
$connect = mysql_connect('localhost','root','ListenToLorieOrDie') or die ("argg");
mysql_select_db('base',$connect) or die ("argg");
mysql_query("INSERT INTO utilisateur VALUES ('666','bofh','[email protected]') ");
$resultat = mysql_query("SELECT id,nom,email from utilisateur");
while ( $ligne = mysql_fetch_array($resultat)){
echo $ligne[id].' - '.$ligne[nom].' - '.$ligne[email].'<br>';
}
mysql_close();
?>
Il y a bien moins longtemps...
<?php
$connexion = new PDO("mysql:host=localhost_hote;dbname=base", ''root'',''ListenToLorieOrDie'');
$resultat=$connexion->query("SELECT id,nom,mail FROM utilisateurs");
$resultat->setFetchMode(PDO::FETCH_OBJ);
while( $ligne = $resultat->fetch() ) // on récupère la liste des membres
{
echo 'Nom : '.$ligne->nom.' - email : '.$ligne->email. '<br />';
}
$resultat->closeCursor();
?>
Il y a encore bien bien moins longtemps :
<?php
class Utilisateur
{
private $id;
private $nom;
private $mail;
public __get($property)
{
return $this->$property;
}
public __set($property, $value)
{
$this->$property = $value;
}
public __construct() {}
public __destruct() {}
}
?>
Il y a encore bien bien moins longtemps :
<?php
class UtilisateurDbAccess
{
public static function create($p)
{
try
{
if (!($u instanceof Utilisateur))
throw new Exception('Erreur impossible de créer l\'utilisateur');
$db = new PDO("pgsql:dbname=pdo;host=localhost", "nom", "mail" );
$request = $dbh->prepare("INSERT INTO utilisateur (nom, mail) values (:nom, :mail)");
$request->bindParam(':nom', $u->nom, PDO_PARAM_STR, 128);
$request->bindParam(':mail', $u->mail, PDO_PARAM_STR, 128)
return $request->execute();
}
catch(Exception $e) { echo $e->getMessage(); }
}
public static function getUtilisateur($id)
{
// renvoyer un utilisateur en fonction de son id ...
}
...
}
?>
Test de doctrine
•
•
•
•
•
Le choix d'utiliser la POO est intéressant et flexible mais gros soucis il faut multiplier les classes par le
nombre de tables. Peux vite devenir galère si en cours de dvt le modèle de données change souvent.
Pour nos tests notre choix va se porter sur Doctrine
Il faut créer notre projet : monProjetDossier/
Ensuite récupérer la bibliothèque doctrine et la mettre dans monProjetDossier/lib/vendor/doctrine/
Sinon on peut utiliser la sandbox Doctrine (cf démo)
// contenu fichierconfig.php (ce fichier par la suite sera inclus dans notre projet (via require_once) :
require_once(dirname(__FILE__) . '/lib/vendor/doctrine/Doctrine.php');
spl_autoload_register(array('Doctrine', 'autoload'));
$manager = Doctrine_Manager::getInstance();
//Création de la chaîne de connexion pour la base de données
$conn = Doctrine_Manager::connection('mysql://root:bla@localhost/db');
Doctrine_Core::loadModels('models');
// Remplace la fonction d'autoload pour la class Doctrine_Core
spl_autoload_register(array('Doctrine_Core', 'modelsAutoload'));
...
Test de doctrine
• Notre MCD :
Test de doctrine
Pour créer le schéma de notre base nous utiliserons un fichier au format YAML.
YAML : acronyme récursif de « YAML Ain't Markup Language » c'est un format adapté à la
representation de données comme XML,JSON... Attention que des espaces pas de tabulations !
• Ex d'un fichier YAML :
# default values
all:
# number of results for pagination
results_number: 30
•
•
ldap:
# params ldap
host: ldapuds.u-strasbg.fr
port: 389
user: cn=app-gestion,ou=accounts,ou=operateurs,o=annuaire
pass: pasfounan
baseuser: o=annuaire
version: 3
exploit:
# informations pages recup email (RE)
titre_RE: Récupération des e-mails @etu.unistra.fr (ldap)
flashOk_RE: adr_ok
Notre schéma YAML pour notre BD
Music:
columns:
title: {type: string(128), notnull: true}
album_id: {type: integer, notnull: true}
relations:
Album: {local: album_id, foreign: id}
Album:
columns:
title: {type: string(128), notnull: true}
relations:
Musics: {type: many, class: Music, local: id, foreign: album_id}
Artists: {class: Artist, refClass: ArtistAlbum, local: album_id, foreign: artist_id}
Artist:
columns:
firstname: {type: string(32), notnull: true}
lastname: {type: string(32), notnull: true}
relations:
Albums: {class: Album, refClass: ArtistAlbum, local: artist_id, foreign: album_id}
ArtistAlbum:
columns:
artist_id: {type: integer, primary: true}
album_id: {type: integer, primary: true}
Gogogadget au générateur de base de données.
<?php
// fichier d'init de la base de données dans un dossier 'models'
require_once('config.php');
Doctrine_Core::dropDatabases();
Doctrine_Core::createDatabases();
Doctrine_Core::generateModelsFromYaml('schema.yml', 'models');
Doctrine_Core::createTablesFromModels('models');
?>
Creer des données dans la base
<?php // sexpistols.php
require_once('config.php')
$album = new Album();
$album->title = 'Nevermind the bollocks';
$album->save();
$music = new Music();
$music->title = 'Anarchy in the UK';
$music->Album = $album;
$music->save();
$music = new Music();
$music->title = 'God save the queen';
$music->Album = $album;
$music->save();
$artist = new Artist();
$artist->firstname = 'Johnny';
$artist->lastname = 'Rotten';
$artist->Albums[] = $album;
$artist->save();
$artist = new Artist();
$artist->firstname = 'Sid';
$artist->lastname = 'Vicioust';
$artist->Albums[] = $album;
$artist->save();
?>
Requêtage
• Doctrine permet de s'affranchir des commandes SQL
• Il propose son propre langage de requêtage : le DQL pour « doctrine query language ».
<?php
$q = Doctrine_Query::create()->from('Artist');
$artists = $q->execute();
foreach ($artists as $artist)
echo $artist->firstname.' '.$artist->lastname."\n";
?>
<?php
$q = Doctrine_Query::create()
->from('Artist a')
->where('a.id <= ? AND a.firstname LIKE ?', array(1, 'Sid%'));
$artists = $q->execute();
foreach ($artists as $artist)
echo $artist->firstname.' '.$artist->lastname."n";
?>
CRUD (Create/Update/Delete)
<?php
$q = Doctrine_Query::create()
->from('Artist a')
->leftJoin('Album al')
->where('a.id <= 1 AND a.firstname LIKE ?', array(1, 'Joh%'))
->execute();
$q2 = Doctrine_Query::create()
->from('Artist a')
->leftJoin('Album al')
->where('a.id <= 1 AND a.firstname LIKE ?', array(1, 'Joh%'))
->execute(array(),Doctrine::HYDRATE_ARRAY);
//debug
echo ''<pre>''. print_r($q). ''</pre> '' ;
echo ''<pre>''. print_r($q2). ''</pre> '' ?>
Jointures
<?php
$q = Doctrine_Query::create()
->from('Artist a')
->leftJoin('Album al')
->where('a.id <= 1 AND a.firstname LIKE ?', array(1, 'Joh%'));
//affiche la requête SQL générée via le DQL
echo $q->getSqlQuery();
?>
Hydratation
•
•
•
Dans Doctrine par défaut on récupère un objet qui encapsule d'autres objets, dans certains cas il n'est
pas nécessaire de stocker l'objet doctrine et l'ensemble de ses entités.
On peut ainsi changer « l'hydratation » de notre objet
Ex : un simple affichage de données il est pratique et benefique pour la mémoire du serveur de ne pas
retourner un objet doctrine complet !
$q = Doctrine_Query::create()->from('TABLE');
// Comportement par défaut, retourne un tableau d'objet
$results = $q->execute(array(),Doctrine::HYDRATE_RECORD);
// Retourne un tableau associatif où les clés sont les noms des champs
$results = $q->execute(array(),Doctrine::HYDRATE_ARRAY);
// Retourne un simple tableau où les champs sont dans l'ordre qu'ils ont été appelés
$results = $q->execute(array(),Doctrine::HYDRATE_NONE);
Hydratation
<?php
$q = Doctrine_Query::create()
->from('Artist a')
->leftJoin('Album al')
->where('a.id <= 1 AND a.firstname LIKE ?', array(1, 'Joh%'))
->execute();
$q2 = Doctrine_Query::create()
->from('Artist a')
->leftJoin('Album al')
->where('a.id <= 1 AND a.firstname LIKE ?', array(1, 'Joh%'))
->execute(array(),Doctrine::HYDRATE_ARRAY);
//debug
echo ''<pre>''. print_r($q). ''</pre> '' ;
echo ''<pre>''. print_r($q2). ''</pre> '' ?>
Les methodes « magiques »
• Les methodes dites « magiques » ou « magic finders » sont très pratiques.
<?php
// Ici on recupère toutes les données de la table Artist
$artists = Doctrine_Core::getTable('Artist')->findAll();
// Récupère la musique qui a pour id 1
$music = Doctrine_Core::getTable('Music')->findOneById(1);
// Récupère le morceau God save the queen
$music = Doctrine_Core::getTable('Music')->findOneByTitle('God Save the queen');
// Récupère l'album qui a pour id 1 si son nom est Nevermind the bollocks
$album = Doctrine_Core::getTable('Album')->findOneByIdAndTitle(1, 'Nevermind the bollocks');
?>
Les transactions
•
•
•
Parfois la mise à jour/insertion de données est incertaine il peut être utile d'utiliser le mécanisme des
transactions.
Tout d'abord il faut pouvoir accéder à l'objet de connexion à notre base :
$conn = Doctrine_Manager::connection(); // la méthode connection renvoie la connexion courante à la
base de données.
Ensuite 3 étapes commencer la transaction / mise à jour (commit) ou retour en arrière (rollback) :
$conn = Doctrine_Manager::connection();
$conn->beginTransaction();
$conn->commit(); // les changements sont appliqués en base
$conn->rollback(); // changements en base annulés en gros control+z :)
Exemple concret de transaction.
<?php
$conn = Doctrine_Manager::connection();
$conn->beginTransaction();
try {
$user = new User();
$user->username = 'marczuckerberg';
$user->password = 'google+casuxamort';
$user->email
= '[email protected]';
$user->save();
$payment = new Payment();
$payment->amount = '200000000K';
$payment->date = '10-02-2012';
$payment->save();
$conn->commit();
} catch(Exception $e) {
$conn->rollback();
}
?>
Conclusion
• Doctrine c'est bon mangez'en !!!!!
• Et bon appétit bien sur !
Références
•
•
•
•
•
•
•
•
http://www.php.net
http://www.phpscripts-fr.net/
http://www.nexen.net/
http://www.phpsecure.info ...
http://phpsec.org
Http://www.siteduzero.com
http://www.phpclasses.org/
Pour les cours :
– http://mastercaweb.u-strasbg.fr/bofh/site/src/
– http://mastercaweb.u-strasbg.fr/bofh/sitemultilingue/src/
– http://mastercaweb.u-strasbg.fr/bofh/src/ ( divers )
– http://mastercaweb.u-strasbg.fr/bofh/compteur.phps ( compteur )
– http://mastercaweb.u-strasbg.fr/bofh/site2leretour/src/
– http://mastercaweb.u-strasbg.fr/bofh/mail/mail.phps
– http://mastercaweb.u-strasbg.fr/bofh/mail/site2boul.phps
– http://mastercaweb.u-strasbg.fr/bofh/bafh/src/
– http://mastercaweb.u-strasbg.fr/bofh/regex/
– http://mastercaweb.u-strasbg.fr/bofh/regex/src/ (regex)
– http://mastercaweb.u-strasbg.fr/bofh/rexex_ep2/
– http://mastercaweb.u-strasbg.fr/bofh/regex_ep2/src/ (regex 2 )
HAPPY
E N D !

Documents pareils