PHP
Un langage en évolution
Pascal MARTIN,
http://blog.pascal-martin.fr
/ pmartin@php.net
/ @pascal_martin
Appuyez sur [s] pour ouvrir les notes présentateur dans une nouvelle fenêtre.
Je vais essayer d'ajouter ici, pour certains slides, des points que j'ai pu donner à l'oral lors de la présentation et/ou qui ne sont pas explicitement écrits sur les slides -- afin de les rendre plus utiles aux lecteurs qui n'auraient pas assisté à la présentation.
Le style sera volontairement un peu oral , se rapprochant un peu de ce qui s'est dit lors de la présentation live .
Un peu d'histoire
Pas mal d'informations sont données dans le manuel : http://www.php.net/manual/fr/history.php ; je ne fais qu'un rapide résumé : les origines de PHP expliquent en partie le langage qu'il est aujourd'hui.
PHP Tools
Suite d'outils créée par Rasmus Lerdorf
1994 : binaires CGI écrits en C
Personal Home Page Tools
Interraction base de données
Applications dynamiques web !
Juin 1995 : diffusion sources
Septembre 1995 : Forms Interpreter
Variables,
Formulaires,
Syntaxe s'intégrant au HTML
1994 : PHP n'est pas si vieux ; il est plus récent que Perl (1987) ou Python (1991) .
PHP n'a pas été créé comme un langage : au départ (et c'est toujours le cas) , le but était d'avoir un truc qui réponde au besoin -- et initialement, le besoin c'était (si j'ai bonne mémoire) de mettre en place un livre d'or !
Personal Home Page : ce nom, qui était un des tout premiers de PHP, date ! Mais correspond bien au rôle de PHP à l'époque.
PHP/FI 2
1996 - 1997
Langage de programmation
Orientation Web forte
Bases de données,
Cookies,
Formulaires,
Fonctions définies par l'utilisateur, ...
Mai 1998 : 60,000 domaines
1 seul développeur
PHP/FI = PHP / Forms Interpreter
Ce n'est qu'avec cette seconde version qu'on commence à parler de langage de programmation .
Reste dans la logique "Web" : PHP a été conçu au départ pour dynamiser des sites web HTML ; ça reste cette idée : mettre des bouts de PHP au milieu du HTML : boucles, variables, ... Avec gestion de ce qui sert à ça : formulaires, cookies, ...
60k domaines = 1% des sites web de l'époque !
PHP/FI 2
<select>
<?$result = msql($database,"select name from categories where name<>'$category' order by name")>
<?$i=0>
<?$num = msql_numrows($result)>
<?while($i<$num)>
<option><?echo msql_result($result,$i,"name")>
<?$i++>
<?endwhile>
</select>
PHP: Hypertext Preprocessor
1997 - 1998
Ré-écriture complète par Ze ev Suraski et And i Gutmans
Nouveau langage,
Nouveau nom,
Extensible (modules en C) ,
Non limité à POSIX.
Juin 1998 : PHP 3.0
Jusqu'à 10% des serveurs web d'Internet
Zeev et Andi bossaient sur un projet e-commerce ; PHP/FI 2 n'était pas suffisant
=> ré-écriture complète, from scratch.
Apparition, avec PHP 3, du nom professionnel de PHP ; nom qui est celui aujourd'hui utilisé : PHP: Hypertext Preprocessor .
Toujours codé en C ; ce qui explique que les extensions soient elles-même en C. Principe qui est toujours vrai aujourd'hui.
Première version de PHP qui marche sous (en particulier) Windows.
Zend Engine
2000 - aujourd'hui
PHP 4 : mai 2000
PHP 5 : juillet 2004
Versions stables : PHP 5.4, 5.5
Version "old-stable" : PHP 5.3
81% des sites web (W³Techs )
"Zend" Engine : Ze ev et And i ;-)
PHP 4 c'était il y a longtemps ; ça n'existe absolument plus aujourd'hui (bon, y'a encore quelques serveurs pas mis à jour depuis 10 ans...) ; si on vous propose un mission PHP 4, fuyez ^^
Au niveau de PHP 5 : ce qui est <= PHP 5.2 n'est plus supporté / maintenu. PHP 5.3 a des correctifs de sécurité (uniquement) pour moins d'un an. Donc, PHP 5.4 et 5.5 = bien ; PHP 5.3 = moué ; le reste = non.
Photo par Jakob Westhoff sur Flickr, CC-BY/NC/SA.
Mascotte du langage : Elephpant ; parce que PHP ça fait un peu un éléphant vu de face.
Existe aussi en rose et en grand modèle. Quelques collectors / éditions limités en vert, rouge, avec logo zend, ...
Quelques fonctionnalités de PHP
Passons au plus intéressant : à quoi est-ce que PHP, en tant que langage, aujourd'hui, ressemble !
Langage de templates
1er rôle de PHP
HTML / PHP
Code entre <?php
et ?>
Typage souple
<?php
$who = "World";
?>
<p>
Hello, <strong><?php echo $who; ?></strong>!
</p>
Langage procédural
API historiquement basée sur des fonctions
Plusieurs milliers !
Encapsulation de fonctions C
Manipulation de chaînes, tableaux, fichiers, ...
Accès DB, réseau, images, ...
Fonctions définies par l'utilisateur
<?php
function say_hello($who) {
echo sprintf("Hello, %s!", ucfirst($who));
}
?>
<p>
<?php say_hello('lyon'); ?>
</>
La bibliothèque standard est remplie d'un énorme paquet de fonctions ; dont beaucoup orientées "web", bien sûr.
Au besoin, installer et/ou activer des extensions (certaines sont fournies / font parti de PHP sans être activées par défaut -- dépend aussi des choix du packageur de la distrib utilisée) pour ajouter des fonctionnalités. Cf [man:Référence des fonctions]
Définition d'un fonction depuis du code PHP : mot-clef function
, nom de la fonction, liste de paramètres, code de la fonction entre {
et }
; [man:Les fonctions]
Langage objet
PHP 5 : fonctionnalités "objet"
Classes / propriétés / constantes / méthodes
Visibilités, Héritage
Constructeur / destructeur, méthodes magiques
Classes abstraites, interfaces
Exceptions
Cf [man:Les classes et les objets]
PHP 4 avait quelque chose qui revenait à des tableaux avec méthodes où tout était public.
Depuis PHP 5, véritable modèle objet ; pas mal inspiré de JAVA.
Visibilités : public
, protected
, private
.
Héritage : simple ; pas d'héritage multiple ; et n'arrivera probablement jamais.
Un exemple de classe
<?php
class MyClass {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getHello() {
return sprintf("Hello, %s!", $this->name);
}
}
$obj = new MyClass("World");
echo $obj->getHello();
Langage objet
Quelques méthodes magiques
<?php
class MyClass {
protected $data;
public function __set($name, $value) {
$this->data[$name] = $value;
}
public function __get($name) {
return isset($this->data[$name]) ? $this->data[$name] : "mahnah mahnah";
}
public function __call($method) {
// Comme si on avait appelé ->nomDeMethode()
}
}
$obj = new MyClass();
$obj->plop = 123456;
$obj->ahha = "Hello";
printf("plop:%d\nahha:%s\ntoto:%s\n", $obj->plop, $obj->ahha, $obj->toto);
plop:123456
ahha:Hello
toto:mahnah mahnah
Méthodes commençant par __
= méthodes magiques .
Exemples : __get
appelée quand on essaye de lire une propriété inexistante, __set
quand on essaye d'écrire dans une propriété inexistante, et __call
quand on essaye d'appeler une méthode inexistante.
Pas forcément considérées comme bonne pratique ; mais avis partagés.
Cf [man:Surcharge magique] et [man:Méthodes magiques]
Exceptions
<?php
$db = new MaDatabase($dsn, $user, $password);
try {
$db->beginTransaction();
$db->query(" ... ");
$db->query(" ... ");
$db->commit();
}
catch (DatabaseException $e) {
$db->rollback();
}
catch (Exception $e) {
// faire quelque chose
}
finally {
$db->close();
}
Exception
est une classe ; les exceptions sont un peu considées, en PHP, comme faisant partie du modèle objet .
try
; catch
de l'exception la plus spécifique à la moins spécifique ; et éventuellement finally
.
finally
: arrivé avec PHP 5.5
Cf [man:Les exceptions]
Quelques highlights
Evolutions des dernières versions de PHP
Espaces de noms
Fonctions anonymes / closures
Traits
Serveur web de test
Générateurs
Evolutions apportées par PHP 5.3, 5.4 (il y a un peu plus d'un an) , et 5.5 (juin 2013, il y a 3 mois) .
Pas mal d'idées reprises d'autres langages ; le but étant de conserver l'idée que PHP permet de développer pour le Web, simplement ; donc fonctionnalités pas nécessaires , mais utiles ; libre à chacun d'en profiter ou non.
Espaces de noms
<?php
namespace Mon\Espace\De\Noms;
class MaClasse {
public function maMethode() {
echo __METHOD__ . "\n";
}
}
<?php
require __DIR__ . '/example-namespace-01.php';
use Mon\Espace\De\Noms\MaClasse;
$obj = new MaClasse();
$obj->maMethode();
Déclaration d'un namespace avec le mot-clef namespace
; séparateur de namespace est \
(on s'y fait, au bout d'un moment) . Cf [man:Les espaces de noms]
use
pour dire qu'on va utiliser ce qui est dans un espace nom ; revient à faire un alias, en fait ; plutôt que d'écrire en entier le nom du NS.
Intérêt : possibilité de déclarer des classes/fonctions de même nom dans des NS différents ; donc, pas de conflit de noms entre différentes bibliothèques qu'on voudrait utiliser en parallèle dans le même projet (genre deux libs définissant une classe Logger
) .
Fonction anonyme
<?php
$data = [ "bonjour", "hello", ];
$result = array_map(
function ($item) {
return ucfirst(str_rot13($item));
},
$data
);
var_dump($result);
array(2) {
[0] =>
string(7) "Obawbhe"
[1] =>
string(5) "Uryyb"
}
array_map()
prend en première paramètre une fonction et en second paramètre un tableau. La fonction est ensuite invoquée sur chaque élément du tableau, un par un.
Ici, on ne déclare pas une fonction nommée , qui ne servirait qu'une fois : on utilise, en ligne, une fonction anonyme. Cf [man:Fonctions anonymes]
Au passage : syntaxe courte pour déclarer des tableaux : arrivée avec PHP 5.4 ; la syntaxe longue étant array( "bonjour", "hello", )
Closure
<?php
$maker = function ($paramMaker) {
$paramMaker *= 5;
return function ($who) use ($paramMaker) {
printf("Hello, %s (%s)\n", $who, $paramMaker);
};
};
$function_1 = $maker(11);
$function_2 = $maker(22);
$function_1("World");
$function_2("Lyon");
Hello, World (55)
Hello, Lyon (110)
Faute de mieux pour expliquer ce qu'est une closure : Wikipedia : Closure (computer science) .
Une fonction anonyme peut utiliser le mot-clef use
pour importer (et binder, d'où la closure) des variables externes à la fonction.
Trait (PHP 5.4)
Réutilisation horizontale
<?php
trait MonTrait {
protected $logger;
public function setLogger(LoggerInterface $logger) {
$this->logger = $logger;
}
public function getLogger() {
return $this->logger;
}
}
<?php
class MaClasse {
use MonTrait;
public function maMethode() {
$this->getLogger()->log("Hello, logger !");
}
}
$obj = new MaClasse();
$obj->setLogger(new UnLogger());
$obj->maMethode();
Globalement, un trait se déclare comme une classe, mais avec le mot-clef trait
. Cf [man:Traits]
Au sein d'une autre classe, use
permet d'importer un trait (on peut en importer plusieurs à la suite les uns des autres) .
En simplifiant un tout petit peu : en interne, ça fait un copier du code du trait, et le colle dans la classe -- qui se retrouve donc avec les propriétés et méthodes définies dans le trait.
Trait (PHP 5.4)
Classe + Interface de l'exemple précédent
<?php
interface LoggerInterface {
public function log($str);
}
class UnLogger implements LoggerInterface {
public function log($str) {
printf("[%s] %s\n", date('H:i:s'), $str);
}
}
Juste pour montrer un exemple d'interface et de classe l'implémentant.
Sur le slide précédent, on peut voir que l'interface est utilisée pour type-hinter le type de paramètre que setLogger()
accepte. Type-hinting qui fonctionne sur array
, des noms de classes, et des interfaces ; pas sur des types scalaires (entier, chaine, flottant, ...) .
Générateur (PHP 5.5)
<?php
$generator = function ($path) {
$file = fopen($path, 'r');
while (!feof($file)) {
yield trim(fgets($file));
}
fclose($file);
};
$iterator = $generator(__DIR__ . '/exemple.txt');
foreach ($iterator as $val) {
echo $val, "\n";
}
Un truc absolument super sympa qui a été sauvagement repompé de Python (le jour de cette présentation, on a eu un exemple de générateur dans la présentation Python juste avant ^^) .
Permet d'itérer sur un ensemble d'éléments sans avoir à charger ceux-ci en mémoire : on les génére un par un.
Cf [man:Generators]
Quelques moins bonnes choses
Tout n'est pas parfait ; beaucoup d'historique
Volonté d'assurer la rétro-compatibilité
register_globals
, magic_quotes
(supprimées !)
Extensions / fonctionnalités obsolètes
API parfois peu consistante
Manque de support complet d'Unicode
goto
Goto par XKCD , CC-BY/NC.
Un des gros objectifs des développeurs de PHP est de ne pas casser la compatibilité : un script écrit pour une version donnée de PHP doit continuer à fonctionner avec la version suivante (en pratique, c'est quasiment toujours le cas ; surtout si le script était correctement développé) .
Cela dit, occasionnellement, on se débarasse de boulet qu'on trainait depuis des années ; ce qui est un progrès !
Mais on ne rendra pas l'API plus consistante : les ordres de paramètres des fonctions sont ce qu'ils sont ; les uniformiser reviendrait à casser tout ce qui existe comme code PHP !
Et, toujours, PHP n'est pas "full unicode" : une chaine de caractères n'est pas une chaine de caractères , mais d'octets ; à vous d'utiliser les bonnes fonctions (il y en a) pour manipuler ces octets si c'est de l'unicode.
Une bande de voleurs !
Des idées reprises d'ailleurs ;-)
Syntaxe : Bash, C, Perl, ...
Modèle objet : JAVA
Fonctions anonymes : Javascript
Traits : Ruby
Generators : Python
Le but de PHP c'est de permettre de faire du web, simplement.
Sauvagement reprendre des fonctionnalités d'autres langages n'est pas tellement un problème (au contraire : c'est comme ça que pas mal de choses sont arrivées dans PHP) ; tant que ça ne complexifie pas (trop) le langage en lui-même ni la maintenance du moteur.
Un langage qui s'est professionnalisé
PHP permet toujours de faire des trucs horribles , bien sûr ; mais depuis quelques années, PHP et son écosystème ont bien évolués, permettant d'en tirer parti dans des applis plus orientées "pro".
Rappel : il n'y a pas de mauvais langage, il n'y a que des mauvais programmeurs.
Des points de rencontre
3 gus sur usenet
AFUP : + de 10 ans, antennes locales
Conférences : Forum PHP / PHPTour ; ZendCon, International PHP Conference, Confoo, SunshinePHP, ...
Apéros PHP / conférences "locales"
Des plate-formes logicielles
PHP, fondation de plate-formes OSS
E-commerce : Magento, Prestashop, ...
CMS : Wordpress, Drupal, Joomla, Mediawiki, ...
Outils / communautés qui s'ouvrent
eZPublish, Drupal : symfony2
Large base de développeurs / installations
Sans parler de la "qualité" de ces outils ou de leur code (il y a des softs là-dedans qui sont presque plus vieux que moi -- en n'exagérant qu'un peu) , de leur avantages, ou de leurs défauts, on ne peut nier qu'ils soient là, et qu'ils aient réussis à se faire une place sur le marché
Et une partie des logiciels cités cherche à s'améliorer ; par exemple, en s'ouvrant à d'autres communautés et/ou à des outils plus généraux -- comme passer à symfony2 plutôt que de dépendre de briques internes.
Dans tous les cas, ces softs, une fois installés, font qu'il y a PHP sur le serveur ; et qu'il devient donc possible de développer/déployer d'autres solutions ;-)
Des utilisateurs "connus"
M6Web, e-TF1,
Euronews, 20minutes, Le Monde Interactif,
France.fr, whitehouse.gov,
Editeurs
PHP est souvent arrivé "par la petite porte"
PHP dans pas mal de grosses boites , ça a été installé sur un serveur pour faire tourner un petit soft (genre un blog d'entreprise) . Puis, vu que PHP était installé, ça a aussi servi à déployer des softs un peu plus gros (genre CMS pour un portail institutionnel) . Et au final, vu que ça marchait bien, des projets entiers ont été lancés en PHP.
Des outils qui murissent
Frameworks de seconde génération
Framework Interop Group
Gestion de dépendances facilitée : Composer
Bonnes pratiques
FIG : il y a des échanges entre frameworks (au sens large) ; le but étant de faciliter l'utilisation au sein d'un projet de briques venant de plusieurs frameworks différents.
PEAR a été utilisé pendant des années comme gestionnaire de dépendances. Ca marchait pas si mal , n'empêche ; même si ça voulait généralement dire installation au niveau système et pas au niveau projet . Composer (arrivé il y a quelque chose comme deux ans ?) vient améliorer les choses à ce niveau ; et est plutôt bien accepté/répandu/utilisé. Cf packagist.org pour un repo de paquets façon CPAN.
IC : souvent avec Jenkins (si pas en externe avec Travis) ; templates php
Au niveau de PHP lui-même ?
Modifications plus structurées (RFC)
Cycle de release + rapide et + clair
Extensions, nouvelles approches
Implémentations alternatives (HHVM)
RFC sont proposées ; puis discutées ; puis votées. Et passent ; ou non.
Une des dernières RFC passées : Syntax for variadic functions , acceptée le 23 sept. 2013.
Une des dernières RFC proposées : Anonymous Classes , proposée le 22 sept. 2013.
En gros une version par an ; objectif = faciliter les montées de versions (moins de différences entre une version et la suivante que si une release tous les 3 ans) , et sortir les nouveautés plus vite.
AOP : extension qui permet de hooker autour de tout appel de fonction/méthode. pthreads : permet de faire du multi-threading en PHP (ce qui ne correspond pas à la philosophie "de base" de PHP, et n'est pas nativement supporté) ; sans souffrir du GIL de Python ;-)
Implémentations de PHP en PHP, en JAVA, ... Ou Facebook (+ gros site au monde ?) qui a codé sa propre implémentation du langage, avec du JIT.
Une visions ?
PHP, un langage...
De templating,
Accessible aux "débutants",
Accessible aux "amateurs", / "bidouilleurs",
Orienté "professionnel" / "entreprise".
Et ces 4 visions se tirent un peu dans les pattes...
Pas de dictateur qui dit "oui" ou "non" pour les évolutions.
Quelques liens
Dernier lien = mon blog ; sur lequel je publie en gros une fois par mois un dépilage de ce qu'il se passe au niveau du développement de PHP.
Questions ?
Il y a eu plein d'échanges pendant la présentation, donc pas vraiment de question à la fin ; et ma batterie touchait à sa fin, et je voulais montrer les slides d'après avant que ça ne coupe ; donc passé vite ici ^^