Langage PHP

Ce document constitue un pense-bête des particularités du langage PHP. Il s'adresse à des programmeurs expérimentés.

Syntaxe comparées de JavaScript, Python et PHP

Chaines

Utiliser les guillemets doubles pour que les variables incluses soient remplacées par leur valeur. Entourez le nom de la variable avec des accolades pour indiquer explicitement son nom.
Concaténation avec l'opérateur "." et non pas "+"
echo "Salut $nom!\nVoici ton résultat: " . monCalcul(); //La conversion nbre vers chaîne est automatique

Chaînes multi-lignes autorisées.

Comme en langage C, printf fonctionne ainsi que l'accès à un caractère par chaine[n] (obsolète) ou $str{n} (actuel); (voir affichage)< P> Dernier caractère: $str{strlen($str)-1}

Exécution d'une commande du shell par $output = `ls -l`;

echo "<PRE>".`dir /B`."</PRE>"

Voir aussi

exec("C:\\repertoire\\nomappli.exe", $output);
var_dump($output);

La longueur d'une chaîne s'obtient par la fonction strlen($chaine), strtolower(str) et strtoupper(str) permettent de changer la casse.

Chaines HereDoc

echo <<<EOT
  Mon "nom" est $colonne. J'affiche $ligneTitres[2].
  Maintenant, j'affiche une variable complexe {$mot[1][$li_colRecherche]}.
  'A' majuscule : \x41 
EOT;
}

Nombres

$n=round(M_PI,4); //3.1416
% = modulo.

expressions régulières

Il existe deux familles de fonctions PHP pour les expressions régulières:
la première (ereg,...) est plus simple, la seconde (preg,..) reprend la syntaxe des expressions régulières PERL.

Expressions régulières (ereg,...)

boolean preg_match(string pattern, string string, array [regs]) //eregi
string preg_replace(string pattern, string replacement, string string) //eregi_replace

if (preg_match("/MERCH/([^/]*)/([^/]*)/([^/]*)/([^/]*)/",$chaine,$regs)){
  $nom=$regs[1];
  $type=$regs[2];
  $pavillon=$regs[3];
  $indicatif=$regs[4];
}

Si regs est fourni, il sera rempli par les résultats de la recherche. $regs[0] contiendra le texte qui satisfait le masque complet, $regs[1] contiendra le texte qui satisfait la première parenthèse capturante, etc..

Expressions régulières (preg,...)

boolean preg_match(string pattern, string string [,array $regs])
string preg_replace(string pattern, string replacement, string string)

//Exemple:
$page=preg_replace("'<script[^>]*>.*?</script>'si","",$page); // le "?" =UNGREEDY

$n=preg_match_all ("|<([^> ]+)[^>]*>[^<]*</\\1>|iU", $html, $matches);
Permet de trouver toutes les balises HTML élémentaires (sans balise incluse) dans la chaine $html. Les éléments répondant au filtre peuvent être retrouvés dans $matches[0][$i]. Pour avoir la liste des balises utiliser $matches[1][$i]. $n est le nombre de résultats qui satisfont le masque complet.

Avec les expressions régulières PERL (preg) on doit délimiter l'expression régulière par un caractère arbitraire (par exemple "/", "|" ou "'").
Le délimiteur final peut être suivi d'options qui affecteront la recherche ("modifiers").

Avec preg les captures doivent être précédées d'un double \
\\1 = première parenthèse capturante.

Remarques

Pour des remplacements simples il est plus efficace d'utiliser
string str_replace(string pattern, string replacement, string string)

Si pattern et replacement sont des tableaux, alors str_replace() ou preg_replace() prennent une valeur dans chaque tableau, et s'en servent pour chercher et remplacer dans string (replacement peut être mis en facteur).

Les fonctions de remplacement peuvent contenir dans le masque de remplacement des références de la forme \n correspondant au texte capturé par la n-ième parenthèse capturante du masque de recherche (\0 correspond au texte qui satisfait le masque de recherche complet.)

\b
limite de mot
\w
caractère alphanumérique y compris "_" et caractères accentués
\d
chiffre (= [0-9])
\s
caractère d'espacement (= [ \t\r\n\f])
\xhh
caractère représenté par son code ASCII en hexadécimal
Remarque: en utilisant des majuscules, on inverse l'effet. Par exemple \W représente un caractère non alphanumérique.

Variables

Il est possible d'écrire plusieurs portions de script en Php, séparées par du code HTML statique car les variables/fonctions déclarées dans une portion de script seront accessibles dans les portions de scripts inférieures.

Une variable précédée du mot clé global sera visible dans l'ensemble du code. Par défaut, les variables globales ne sont pas connues à l'intérieur du corps d'une fonction. On peut cependant rendre visible une variable globale à l'aide du mot-clé global (dans le corps de la fonction).

global variable_externe;

Le niveau static permet de définir une variable locale à la fonction, qui persiste durant tout le temps d'exécution du script. Par défaut, la variable possède le niveau local.

$REMOTE_ADDR est une pseudo variable qui donne l'IP du client.

Tableaux

$tableau=array();
echo sizeof($tableau);
sort($tableau);

$data = "didier:*:1023:1000::/home/foo:/bin/sh";
list($user, $pass, $uid, $gid, $gecos, $home, $shell) = explode(":", $data);

$chaine=join("\t",$tableau); // ou "implode"

Les tableaux stockent des données sous forme de liste. Les données contenues dans la liste sont accessibles grâce à un index (un numéro représentant l'élément de la liste). Contrairement à des langages tels que le langage C, il est possible de stocker des éléments de types différents dans un même tableau.

Ainsi, pour désigner un élément de tableau, il suffit de faire suivre au nom du tableau l'indice de l'élément entre crochets:

$Tableau[0] = 12; $Tableau[1] = "CCM"; 

Avec PHP, il n'est pas nécessaire de préciser la valeur de l'index lorsque l'on veut remplir un tableau, car il assigne la valeur 0 au premier élément (si le tableau est vide) et incrémente les indices suivants. De cette façon, il est facile de remplir un tableau avec des valeurs. Le code précédent est équivalent à:

$Tableau[] = 12; $Tableau[] = "CCM"; 

tous les types de variables peuvent être contenus dans un tableau

Lorsqu'un tableau contient d'autres tableaux, on parle de tableaux multidimensionnels. Il est possible de créer directement des tableaux multidimensionnels en utilisant plusieurs paires de crochets pour les index (autant de paires de crochets que la dimension voulue). Par exemple, un tableau à deux dimensions pourra être déclaré comme suit:

$Tableau[0][0] = 12; 
$Tableau[0][1] = "CCM"; 
$Tableau[1][0] = 1245.652; 
$Tableau[1][1] = "Au revoir"; 
Certaines configurations de PHP rendent disponible tous les paramêtres de GET et POST sous la forme de variables. La fonction import_request_variables() permet de rendre cela vrai pour les configurations ou ce fonctionnement est désactivé par défaut.

Variables tableaux associatifs

PHP permet l'utilisation de chaînes de caractères au lieu de simples entiers pour définir les indices d'un tableau, on parle alors de tableaux associatifs. Cette façon de nommer les indices peut parfois être plus agréable à utiliser:

$Toto["Age"] = 12; 
$Toto["Adresse"] = "22 rue des bois fleuris"; 
$Toto["Nom"] = "Ah, vous auriez bien aimé connaître le nom de famille de Toto..."; 

Retour d'un tableau par une fonction

function petit_nombre() {
    return array (0, 1, 2);
}
list ($zero, $one, $two) = petit_nombre();

Parcours d'un tableau

echo "Valeurs transmises par la méthode POST";
reset ($_POST);
while (list ($key, $val) = each ($_POST)) {
echo "$key => $val<br>";
}

Formulaires

$nom=stripslashes($_REQUEST['nom']); // récupère la valeur "nom" dans script.php?nom=Merle+d'Aubign%E9

Les variables transmises dans la query-string sont directement accessibles sauf si celà a été désactivé dans le php.ini du serveur (register_globals = Off )

@import_request_variables("gpc"); importera les variables GET, POST et COOKIE. 

Ou
$_REQUEST = array_map('stripslashes', $_REQUEST);
extract($_REQUEST); //Permet de se débarasser des slashes

Upload de Fichier

<form action="cible.php" method="post" enctype="multipart/form-data"> <INPUT TYPE="hidden" name="MAX_FILE_SIZE" value="1000"> (en octets doit précéder fichier. Une autre limitation est dans php.ini upload_max_filesize (2 Mo par défaut). Emplacement du fichier texte: <input type="file" name="fichier" /> Le traitement se fait dans le script cible.php avec $_FILES["fichier"]['tmp_name'] = Le nom temporaire du fichier qui sera chargé sur la machine serveur.

Egalement disponibles: $_FILES["fichier"]['name'] - Le nom du fichier original sur le système de l'envoyeur, $_FILES["fichier"]['size'] - La taille du fichier envoyé en octets, $_FILES["fichier"]['type'] - Le type MIME du fichier, si le navigateur a fourni cette information. Par exemple, "image/gif".

tableaux de variables globales

Ces variables globales sont aussi automatiquement importés dans les corps des fonctions. Recuperer les variables passées par GET ou POST avec (respectivement) $var=$_GET['var']; ou $var=$_POST['var'];. Gerer les sessions avec $_SESSION.
$_SESSION['username'] plus précis que $username;
$_COOKIE['mavar']
$_GET['mavar']
$_POST['mavar']
$_REQUEST['mavar'] variable venant de GET, POST ou COOKIE (depuis PHP 4.0.6)
$_SERVER['REMOTE_ADDR']
$_ENV variables d'environnement
$_FILES fichiers uploadés
$GLOBALS Variables globales 

extract($_REQUEST) est équivalent à import_request_variables("gpc")

Sessions

On peut demander la persistance d'une variable globale $mavar1 côté serveur (voir session.save_path dans php.ini) par

session_register("mavar1");
(sans le "$"). Ce type d'instruction doit se trouver en tête du code. Une session est automatiquement générée la première fois. On pourra alors utiliser cette variable dans toutes les pages qui débutent par
session_start();

Pour plus de sureté (si cookies verrouillés) les liens peuvent intégrer le SID. echo '<A href="url.htm?'.SID.'">lien</A>';

Exemple de page 1

session_start();
$_SESSION['couleur'] = 'vert';

// Fonctionne si le cookie a été accepté
echo '<a href="page2.php">page 2</a> ';

// Ou bien, en indiquant explicitement l'identifiant de session
echo '<a href="page2.php?' . SID . '">page 2</a>';
Exemple de page 2
session_start();
echo $_SESSION['couleur']; // vert

Fonctions

function Nom_De_La_Fonction(type1 argument1, type2 argument2, ...) { liste d'instructions }

Une autre méthode pour modifier une variable consiste à la faire précéder du caractère &, précisant qu'il s'agit alors d'un alias: la valeur de la variable est modifiée à la sortie de la fonction. On parle alors de passage par référence. Dans ce cas on passe la référence (adresse mémoire) de la variable à la fonction, ce qui permet de modifier sa valeur.

Les paramètres optionnels sont autorisés : il suffit de leur affecter une valeur par défaut.

Objets

$Nom_de_l_objet = new Nom_de_la_classe(); 
$Nom_de_l_objet->Nom_de_la_donnee_membre = Valeur;
$Nom_de_l_objet->fonction_membre(parametre1,parametre2,...); 

Le mot clé $this permet de désigner l'objet dans lequel on se trouve, c'est-à-dire que lorsque l'on désire faire référence dans une fonction membre à l'objet dans lequel elle se trouve, on utilise this.

"->" : Propriété d'un objet Permet d'accéder aux données membres d'une classe $MonObjet->Propriete

class Toto{ var $age; var $sexe; var $adresse; 
function setAge($Age){ $this->age = $Age; } } 

PHP, dans sa version 3, reste assez limité du point de vue de la programmation objet. La plupart des aspects marquants de la programmation objet ne sont pas présents dans le langage:

L'héritage simple est possible en utilisant extends.

Note: le constructeur de la classe mére n'est pas appellé automatiquement. Il convient donc de le faire si nécessaire au sein du constructeur fils.

 This->NomClasseMere()

Il n'y a pas notion de destructeur d'objet en PHP3.

L'héritage multiple n'existe pas.

Il n'y a pas de méthodes et attributs privés. Tout est public et accessible de l'extérieur.

Un objet instancié n'est pas une référence ( un pointeur) mais une variable, sorte de ``tableau associatif muni de methodes'' => par affectation simple on copie!

Affichage

Fonctions

print_r(variable)
Pour afficher tableaux et objets: génère le HTML adéquat. Utile pour le déboggage.
$texte=number_format(nombre,decimales, dec_point, thousands_sep)

Le caractère $ a un rôle particulier dans la mesure où l'interpréteur le comprend comme une variable, ce qui signifie que lorsque le caractère $ est rencontré dans la chaîne qui suit la fonction echo, l'interpréteur récupère le nom de la variable qui suit le caractère $ et le remplace par sa valeur. Dans l'exemple suivant par exemple, on assigne la date actuelle à une variable appelée $MaDate, puis on l'affiche sur le navigateur:

$MaDate = date("Y"); echo "Nous sommes en $MaDate"; 
Syntaxe dates: date("d/m/Y G:i:s", filemtime($file)) Il existe beaucoup d'options... (w - Jour de la semaine, numérique, i.e. "0" (Dimanche) et "6" (Samedi))
Si le deuxième argument (timestamp) n'est pas fourni: date courante.

printf

%c Caractère codé par son code ASCII
%d Entier en notation décimale
%e Type double (nombre à virgule) au format scientifique (1.76e+3)
%f Type double (nombre à virgule)
%s Chaîne de caractères

Constantes

function rapport_erreur($file, $line, $message) 
{ echo "Une erreur a eu lieu dans le fichier $file à la ligne $line: $message."; } 

rapport_erreur(__FILE__,__LINE__, "Y a un problème!"); 

define('NOM','TOTO');

Erreurs

Utiliser @ avant une fonction dont on veut taire l'erreur. error_reporting(0); //tait les erreurs

error_reporting (E_ERROR | E_WARNING | E_PARSE | E_NOTICE); //Erreurs courantes error_reporting (E_ALL); // rapporte toutes les erreurs PHP voir aussi E_NONE

PHP autorise l'utilisation de la commande exit(), qui permet d'interrompre totalement l'interprétation du script, ce qui signifie que le serveur n'envoie plus d'informations au navigateur: le script est figé dans son état actuel. cette instruction est particulièrement utile lors de l'apparition d'erreur!

La méthode die(chaine) est aussi utile: elle regroupe un echo et exit.

ereg( ...) or die('chaine mal formatée);

Fichiers

$fp=fopen("mail.log","a");
fwrite($fp,"$REMOTE_ADDR (".gethostbyaddr($REMOTE_ADDR).")n");
fclose($fp);

On peut aussi utiliser ces fonctions pour lire ou écrire via http ou ftp.

$fichier = join( '', file( "php://stdin" ) );

Fichier inclus

Les fichier inclus sont des fichiers PHP traditionnels. Leur extension est .inc par convention, mais rien n'empêche d'utiliser .php
Le code qui est dans le fichier doit être placé entre les balises habituelles de PHP.

On inclus un fichier en utilisant include ou require.

Il existe une différence importante entre les deux :

Exemple d'intérêt:

if ($user == "Administrateur" )  
	{include 'admin_fonctions.inc';} //mettre entre { } 

A l'intérieur d'un fichier inclus, tout se passe comme si l'on était dans l'élément parent pour la visibilité des variables. Par contre pour l'instruction "return", include se comporte comme une fonction (en PHP4). Exemple:

if (!include('navire_affichage.inc')) return false;

Header

header("Content-disposition: filename=$db.sql");
header("Content-type: application/octetstream");

header("Pragma: no-cache");
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date dans le passé


header("Expires: 0");
header("Location: http://www.php.net/"); //url relatives=OK

header("Status: 301 Moved Permanently");
header("Location: http://www.site.com/index-$capture[2].html");

// si on génère du javaScript
header("Content-type: application/x-javascript");




Client OS

    $crlf="\n";
    $client = getenv("HTTP_USER_AGENT");
    if(preg_match("/[^(]*((.*))[^)]*/",$client,$regs)) 
    {
        $os = $regs[1];
        if (preg_match("/Win/i",$os)) 
            $crlf="\r\n";
    }
}

PHP.EXE

Usage: php [-q] [-h] [-s [-v] [-i] [-f ] |  { [args...]}
  -q             Quiet-mode.  Suppress HTTP Header output.
  -s             Display colour syntax highlighted source.
  -f       Parse .  Implies `-q'
  -v             Version number
  -C             Do not chdir to the script's directory
  -c       Look for php.ini file in this directory
  -d foo[=bar]   Define INI entry foo with value 'bar'
  -e             Generate extended information for debugger/profiler
  -z       Load Zend extension .
  -l             Syntax check only (lint)
  -m             Show compiled in modules
  -i             PHP information
  -h             This help

Ecriture d'exécutables

<?
//Ce programme qui convertit STDIN marche sous MS-DOS
//appel par k:babelEasyPHPphpphp -q urlencode.php <fichier_source >fichier_destination
//On peut aussi placer cette commande dans un fichier BAT pour utilisation par glisser déposer.

$in=fopen("php://stdin","r");
$buffer='';
$CRLF="\r\n";
if (!$in)  die("pas reussi à ouvrir STDIN");


while(!feof($in)) {
    
    $buffer = trim(fgets($in, 4096));
	echo urlencode($buffer).$CRLF;
}
?>

PHP-GTK, permet d'écrire des applications autonomes sous Unix ou Windows

Authentification

Les restrictions d'accès simples de type "HTTP Basic" ( comme ceux générés via .htaccess ) peuvent être directement implémentés via un script php.
Exemple:

if ( !isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW']) 
	|| ($_SERVER['PHP_AUTH_USER'] !== "nom_d_utilisateur" )
	|| ($_SERVER['PHP_AUTH_PW'] !== "mot_de_passe") ) 
{
   header('WWW-Authenticate: Basic realm="Authentifiez vous"');
   header('HTTP/1.0 401 Unauthorized');
   echo 'Acces non autorisé';
   exit;
}

echo 'Utilisateur authentifié';

Bases de données

//Proxad
$base='mondomaine';
$login='mondomaine';
$pwd='monpassword';

$db=mysql_connect("sql.mondomaine", $login, $pwd);

mysql_select_db($base,$db)

Mail

mail(emaildest,objet,corps,[entetes])
on spécifie le serveur SMTP et l'adresse expéditeur dans la section [mail function] de php.ini

entetes="From: spammer@b.comrnReply-to: noone@b.comrnBcc: noone@b.com" //Attention CRLF et non pas LF

On peut utiliser

$fichier=chunck_split(base64_encode($fichier)); si l'on veut incorporer une PJ.
Il faut à ce moment définir manuellement les entêtes et délimiteurs MIME.

Parseur XML

Similaire à SAX: analyse linéaire du document XML, avec appel de 3 fonctions différentes: C'est au sein de ces 3 fonctions que l'on fait une analyse en fonction de l'élément en cours, l'info étant transmise par les paramètres. Utiliser une variable persistante pour détecter à quel élément parent appartiennent les données.

$fp=fopen("test.xml","r");
$parseur=xml_parser_create();
xml_set_element_handler($parseur,"debutElement","finElement");
xml_set_character_data_handler($parseur,"donnees_car");

while($tampon=fread($fp,4096)) xml_parse($parseur,$tampon,feof($fp));
xml_parser_free($parseur);

Images

Pour afficher du texte on utilise une Police True Type, il faudra la mettre dans le même répertoire que le fichier php.

Exemples: "Hello World" dans carré noir, suivi d'un histogramme.

<?php 
 Header("Content-type: image/gif"); 
 $im = imagecreate(200,100); 
 $black = ImageColorAllocate($im, 0,0,0); //Première attribuée -> couleur du fond
 $white = ImageColorAllocate($im, 255,255,255);  
 ImageFilledRectangle($im,0,0,200,100,$black); 
 //j'ecris mon Hello 
 ImageTTFText($im, 30, 340, 15, 20, $white, "arial.ttf","hello world");  
 ImageGif($im); //envoie l'image
 //ImageJPEG($image,"image.jpg",qualite) crée un fichier avec qualite=0 à qualite=100 (70=defaut)
 ImageDestroy($im);  
?>  



<?php 
Header("Content-type: image/gif"); 
$x=400; 
$y=300; 
$data=array (3, 1, 7, 2, 5, 4, 6); 
$im = imagecreate($x,$y); 
//$im=ImageCreateFromJPEG("image.jpg");
$black = ImageColorAllocate($im, 0,0,0); 
$blue = ImageColorAllocate($im, 0,36,135); 
$white = ImageColorAllocate($im, 255,255,255); 
ImageFilledRectangle($im,0,0,$x,$y,$white); 
ImageLine($im,0,50,$x,50,$black); 
ImageLine($im,$x-50,0,$x-50,$y,$black); 
ImageTTFText($im, 12, 45,$x-40,40, $black, "arial.ttf","exemple");  
//Voir aussi ImageString($im, $font, $x,$y,$message, $couleur) avec $font un numéro (entre 1 et 5)
for($i=0;$i<sizeof($data);$i++) 
{ 
 ImageFilledRectangle($im,$i*50+15, 
51,$i*50+40,51+$data[$i],30,$blue); 
} 
ImageGif($im); 
ImageDestroy($im); 
?>  

ImageFilledPolygon($im,$tableau,$taille_tableau,$couleur)
read_exif_data($fichierJpeg) retourne un tableau avec entêtes EXIF

Configuration

Un des principaux paramêtres défini dans php.ini est max_execution_time qui fixe la durée max d'un script (par défaut 30s).

On peut ponctuellement contourner cette limitation par la fonction: set_time_limit (45);

Ignoré en "safe mode".

Compression

Il suffit de commencer le code par:

ob_start("ob_gzhandler");

On peut terminer la page par:
ob_end_flush();

Cookies

Le 3ème argument de setcookie est optionnel. Si pas de timeout: cookie de session.


time() retourne valeur en secondes pour date/heure actuelle.

setcookie("name", "value", timeout);
$expireTime = time() + 60*60*24*7;   # 1 week from now
setcookie("CouponNumber", "389752", $expireTime);

Templates avec structures de contrôle

On peut utiliser une syntaxe similaire aux templates Jinja de Python
<?php if ($a == 5): ?>
A vaut 5!!
<?php endif; ?>
Idem pour elseif (..): else: for(..): endfor,...

Remarque c'est uniquement pour la clarté de lecture qu'il faut utiliser cette syntaxe alternative, pour éviter les
<?php }; ?>

Comparaison de JavaScript et PHP

En PHP les ";" de fin de ligne sont obligatoires, les noms de variables sont précédés de $
JavaScriptPHP
var i=3$i=3;
str.lengthstrlen($str)
table.lengthsizeof($table)
tabArgs=foo.arguments$tabArgs = func_get_args();
var tab=[];$tab=array();
'Bonjour '+prenom'Bonjour '.$prenom ou "Bonjour $prenom"
pays.capitalepays['capitale']
parseInt(valeur)intval($valeur)
for (var key in obj) alert(key+'='+obj[key])foreach($obj as $key => $val) echo "$key=$val\n";
str.toUpperCase()strtoupper($str)

PHP en ligne de commande

Ajouter au $PATH le dossier contenant php.exe (et l'indispensable php5ts.dll)

php -h
php test.php
php -r  phpinfo();

PHP et UTF-8

utf8_encode

ligne de commande

Vous pouvez écrire des scripts PHP et les exécuter en ligne de commandes, sans l'aide d'un serveur web et d'un navigateur (scripts de "cron" (Linux) ou task manager (Win32), opérations sur des fichiers etc.). Il vous suffit pour cela de disposer de l'exécutable PHP.

PHP-GTK

Avec PHP yon peut aussi faire des applications (desktop GUI applications) via l'extensionPHP-GTK. On ne génère plus du HTML, mais on gère fenètres et objets. PHP-GTK est une extension de PHP, qui n'est pas fournie dans la distribution de base. PHP-GTK est multi plateformes. L'alliance de PHP et GTK+ va permettre de créer des interfaces graphiques telles que nous en voyons dans des applications générées en Visual Basic, C++, Java ou Delphi.