Tutoriel Vidéo PHP PHP "c'est de la merde"

Télécharger la vidéo

Même si PHP est un langage qui est extrêmement répandu, il est souvent la source de critiques et de moqueries sur internet. Il suffit de se rendre sur certaines communautés de développeurs pour s'en rendre compte. Aussi, je vous propose aujourd'hui de nous attarder sur les critiques faites à l'égard de PHP afin de mieux les comprendre.

"PHP n'est pas un vrai langage de programmation"

Une des premières critiques faites à l'égard de PHP est tout simplement de dire que PHP n'est pas un véritable langage de programmation. Cette critique est souvent faite par des personnes qui ont testé PHP il y a un petit moment de cela mais qui n'ont pas forcément suivi son évolution. Mais derrière cette critique, se cache une part de vérité, et il faut revenir sur l'historique de PHP pour le comprendre.
PHP est un langage particulier parce qu'il n'a pas commencé comme langage de programmation, mais comme une suite d'outils permettant de créer des éléments dynamiques sur une page Web. Les premières versions de PHP ressemblaient plus à un moteur de template qu'à un véritable langage de programmation. On mélangeait dans le code HTML des commentaires qui allaient être interprétés par le moteur de PHP. Par exemple la version 2.0 de PHP ressemblait à ça :

<!--include /text/header.html-->

<!--getenv HTTP_USER_AGENT-->
<!--ifsubstr $exec_result Mozilla-->
  Hé, vous utilisez Netscape !<p>
<!--endif-->

<!--sql database select * from table where user='$username'-->
<!--ifless $numentries 1-->
  Désolé, cette ligne n'existe pas<p>
<!--endif exit-->
  Bienvenue <!--$user--> !<p>
  Vous avez <!--$index:0--> crédits sur votre compte.<p>

<!--include /text/footer.html-->

Il faudra attendre la sortie de la version 3.0, qui sortira 4 ans après la création de la première version de PHP, pour que le langage ressemble à ce que l'on connaît aujourd'hui. Malgré tout, le langage reste relativement simple par rapport à ce que l'on peut retrouver dans d'autres langages de programmation.
C'est avec l'apparition de la version 5.0 que PHP deviendra un langage de programmation plus robuste avec l'apparition d'un nouveau modèle objet qui va permettre d'organiser le code convenablement (en permettant par exemple de déclarer les variables en public ou en privé, de pouvoir utiliser un système de traits pour de l'héritage multiple, et de créer des interfaces pour améliorer l'interopabilité du code).

L'historique de PHP reste gravé dans son ADN est fait que le langage a cette capacité d'être à la fois un langage qui peut servir de moteur de template mais aussi de véritable langage de programmation où l'on va pouvoir créer des classes et organiser le code convenablement. En PHP on retrouvera du code très procédural qui peut ressembler à cela :

<?php if (strpos($_SERVER['HTTP_USER_AGENT'], "Firefox") !== false): ?>
  <p>Hé, vous utilisez Firefox !<p>
<?php endif; ?>

<?php $posts = mysqli_num_rows(mysqli_query($conn, 'SELECT * FROM wp_posts'));
<?php if ($posts === 0): ?>
  <p>Désolé, cette ligne n'existe pas<p>
<?php else: ?>
  <p>Bienvenue !<p>
  <p>Vous avez écrit <?= $posts; ?> articles !
<?php endif; ?>

Mais aussi du code plus organisé et plus testable qui ressemblera plutôt à cela :

<?php

namespace App\Basket\Table;

use App\Auth\User;
use App\Basket\Basket;
use App\Basket\BasketRow;
use App\Basket\Entity\Basket as BasketEntity;

class BasketTable extends Table
{

    public function findForUser(int $userId): ?BasketEntity
    {
        return $this->makeQuery()->where("user_id = $userId")->fetch() ?: null;
    }

    public function createForUser(int $userId): BasketEntity
    {
        $params = [
            'user_id' => $userId
        ];
        $this->insert($params);
        $params['id'] = $this->pdo->lastInsertId();
        return Hydrator::hydrate($params, $this->entity);
    }

    public function addRow(BasketEntity $basket, Product $product, int $quantity = 1): BasketRow
    {
        $params = [
            'basket_id'  => $basket->getId(),
            'product_id' => $product->getId(),
            'quantity'   => $quantity
        ];
        $this->basketRowTable->insert($params);
        $params['id'] = $this->pdo->lastInsertId();
        /** @var BasketRow $row */
        $row = Hydrator::hydrate($params, $this->basketRowTable->getEntity());
        $row->setProduct($product);
        return $row;
    }

    public function updateRowQuantity(BasketRow $row, int $quantity): BasketRow
    {
        $this->basketRowTable->update($row->getId(), ['quantity' => $quantity]);
        $row->setQuantity($quantity);
        return $row;
    }

    public function deleteRow(BasketRow $row): void
    {
        $this->basketRowTable->delete($row->getId());
    }

    public function findRows(BasketEntity $basketEntity): array
    {
        return $this->basketRowTable
            ->makeQuery()
            ->where("basket_id = {$basketEntity->getId()}")
            ->fetchAll()
            ->toArray();
    }

    public function deleteRows(\App\Basket\Entity\Basket $basket)
    {
        return $this->pdo->exec('DELETE FROM baskets_products WHERE basket_id = ' . $basket->getId());
    }
}

Aussi, aujourd'hui PHP propose de nombreuses fonctionnalité et on retrouvera tous les outils nécessaires à la création d'application complexe.

"PHP est un langage de débutant"

PHP, par sa manière de fonctionner, est très intéressant pour les personnes qui débutent en programmation. Il permet à une personne qui vient d'apprendre l'HTML de créer des éléments dynamiques sans forcément comprendre tous les aspects de la programmation ou de la création d'un serveur. On peut par exemple commencer à utiliser PHP pour découper des pages en plusieurs parties en utilisant la fonction include sans forcément écrire de réel algorithme. L'effet perverse de cette accessibilité, est que l'on retrouvera sur Internet beaucoup de "mauvais codes" (du code mal organisé ou avec des failles de sécurité) ce qui renforce cette impression que PHP est un langage de débutants.

Mais ce n'est pas parce que PHP est utilisé par les débutants, qu'il est réservé pour autant aux débutants. Il existe aujourd'hui de nombreux Frameworks qui permettent de créer un code propre et organisé pour des projets complexes et certains projets ont prouvés qu'il est possible d'utiliser PHP dans un cadre professionnel (Facebook, Wikipedia...). De la même manière l'écosystème autour de PHP a beaucoup évolué et l'apparition de composer (un gestionnaire de paquet) par exemple permet d'encourager la communauté à produire du code plus robuste.

PHP est du coup un langage intéréssant car il vous permet de commencer rapidement et d'être productif rapidement tout en offrant une profondeur suffisante pour faire évoluer le code au fur et à mesure de l'apprentissage.

"PHP est lent"

En soit, PHP n'est pas forcément moins performant que les autres langage, mais son modèle d'exécution est plus critiquable. Avec PHP, pour chaque requête faite au niveau du serveur, PHP doit lire l'ensemble des fichiers, les interpréter et ensuite éxécuter le code généré (OPCode). Ce modèle exécution est problématique car la vitesse d'éxécution d'une page est limitée par la lecture sur le disque (extrèmement lente par rapport à la vitesse d'éxécution d'un processeur) ce qui rend l'application très lente (le problème est amplifié par le nombre de fichier à lire).
Cela fut un problème jusqu'à la version 5.5 de PHP qui intègre l'extension OPcache. Cette extension va être capable de mettre en mémoire le code interprété par PHP (l'OPCode) et permet de sauter les étapes de lecture et d'interprétation des fichiers. L'activation de cette extension permet d'obtenir des performances beaucoup plus intéressantes pour PHP (on peut diviser par 20 les temps de chargements sans rien changer au code).
Il reste cependant la phase d'éxécution du code qui est une étape supplémentaire par rapport à d'autres langages de programmation. Pour chaque requête faite auprès du serveur, PHP devra exécuter l'entièreté du code pour générer la page Web là où d'autre langages n'auront besoin de n'éxécuter que la partie logique spécifique à la page en question (les objets étant conservé en mémoire lors du lancement du serveur). Cette phase d'initialisation peut effectivement coûter quelques ms et placer PHP derrière d'autres languages.

En revanche, même si ce modèle d'exécution a un petit inconvénient en termes de performance, il a un énorme avantage en terme de stabilité. Chaque requête est traitée de manière individuelle, si une page contient une erreur, elle n'entraîne pas un plantage global du serveur et on limite aussi la possibilité de fuites mémoires.

"PHP est inconsistant"

PHP est malheureusement un langage qui est assez inconsistant et qui est plein de surprises. Une grosse partie des problèmes provient de son origine "petit outil personnel" et son dévouement à la rétrocompatibilité (PHP s'efforce au fur et à mesure des nouvelles versions de maximiser la compatibilité et d'éviter au maximum de casser les choses).
Le problème avec ce travail de rétrocompatibilité est que PHP garde des fonctions qui sont dans le code depuis les premières versions, et qui n'ont pas forcément été nommées ou organisées convenablement. Du coup, par rapport à d'autres langages les fonctions sont très mal organisées, très mal nommées et possèdent des paramètres avec des ordres inconsistants ce qui est une source importante de bug.

// underscore ou pas ?
base64_encode/urlencode

// to ou 2 ?
bin2hex(), deg2rad(), strtolower(), strtotime()

// Ordre des arguments
array_filter($input, $callback);
array_map($callback, $input);

strpos($haystack, $needle);
array_search($needle, $haystack);

// Souvent plusieurs options pour faire la même chose 
/*
mysqli ou PDO ?
(new DateTime()) ou date_modify()
Pourquoi autant de librairie pour gérer des XML ? https://secure.php.net/manual/en/refs.xml.php 
*/

C'est à cause de cela par exemple que beaucoup de développeurs PHP ont recours à la création de classes intermédiaires pour faire des opérations basiques (des classes Collection pour gérer les tableaux, des classes statiques Str pour la manipulation de chaines...).

Un autre problème, qui a plutôt tendance à affecter les débutants est l'utilisation d'un typage faible. Ce typage va convertir le type d'une variable suivant le contexte ce qui peut amener à de nombreux problèmes et aussi à certaines inconsistances. La plupart des problèmes peuvent être mitigés en utilisant des vérifications strictes (=== au lieu de ==). Ce n'est pas un problème qui est propre à PHP mais qui affecte tous les langages à typage faible de manière générale (JavaScript possède des problèmes similaires par exemple).

var_dump("6" == " 6"); // true
var_dump("foo" == 0); // true
var_dump(NULL < -1); // true
var_dump(NULL == 0); // true

L'autre chose qui peut être pas mal frustrant avec PHP est l'inconsistance au niveau même de la syntaxe. Vu que PHP n'a pas été designé comme langage de programmation ils ont dû prendre à droite et à gauche différente idées pour concevoir le langage et on se retrouve du coup avec un mélange de syntaxe qui peut être assez déstabilisant.

  • . pour concaténer des chaines, + pour ajouter des nombres mais un seul symbole == pour comparer.
  • -> pour accéder à une propriété / méthode d'un objet
  • :: pour l'appel à des méthodes statiques
  • \ pour les namespaces
  • Les classes s'écrivent comme en Java, les variables comme en Perl.

Enfin, le langage ne gère pas l'unicode convenablement, ce qui peut amener à de nombreux problèmes pour un développeur non aguerri :

// Je cherche la taille de la chaine "10 €"
strlen('10 €'); // 6
mb_strlen('10 €'); // 4

Les fonctions basiques ne gèrent pas l'encodage à octet variable, et comme souvent la solution choisie a été d'ajouter de nouvelles fonctions ce qui emmène a encore plus de confusions.

Pour le coup, si vous valorisez la "beauté" du code, PHP n'est pas forcément le langage indiqué. Ceci dit il a le mérite d'essayer de conserver au maximum la compatibilité au fil des versions ce qui permet d'assurer des mises à jour "en douceur".
Dans le pire des cas, on peut créer par-dessus les fonctionnalités de base du langage une série de classe pour travailler avec plus de cohérence.

"PHP ne gère pas la concurrence"

Pour rappel, le principe de concurrence est la capacité qu'a un langage ou une technologie d'effectuer plusieurs opérations en parallèle. PHP est donc un langage synchrone, où chaque opération doit être terminée avant de passer à la suivante.

PHP est un langage qui a été conçu il y a un petit moment de cela, et comme beaucoup de "vieux" langages il ne gère pas convenablement la concurrence.
En revanche son modèle d'exécution gère la concurrence car chaque requête faite auprès de PHP est géré par un processus différent ce qui permet au système de gérer plusieurs requêtes en parallèle.
Mais, si pour certaines pages vous avez des traitements lourds à effectuer, le côté synchrone de PHP n'est pas forcément bloquant. Vous pouvez par exemple mettre en place un système de files d'attente qui va vous permettre de gérer les tâches complexes (comme le traitement d'images ou de vidéos) de manière séparée afin de ne pas impacter les performances de votre application. Certains Framework, comme Laravel, offre d'ailleurs des systèmes pour mettre en place facilement de tel systèmes.
Il est aussi intéressant de noter que si vous concevez un outil en ligne de commande en utilisant PHP vous avez accès à l'extension pthreads qui permet de gérer plusieurs threads.

Comme toujours, il faudra choisir l'outil en fonction de vos besoins. PHP est un langage et une technologie qui est intéressante pour la génération de pages Web mais qui a ses limites pour d'autres utilisations. Il est possible de contourner les problématiques de concurrence de PHP en utilisant un système de file d'attente, mais si votre application nécessite la création de tâches concurrentes il faudra alors se renseigner sur d'autres langages et même peut être utiliser plusieurs langages en même temps (continuer à générer les pages Web en utilisant PHP et déléguer les traitements lourds à un autre langage de programmation).

"NodeJS > all, PHP c'est mort"

À chaque fois qu'une technologie voit le jour, beaucoup annoncent la mort de la technologie qui la précède et PHP ne fait pas exception à cette règle.
Comme précisé dans l'introduction, PHP est une technologie qui est extrêmement répandue sur Internet et il est assez difficile d'imaginer sa mort dans un futur proche. En plus de cela, la communauté autour de PHP continue de grandir et de faire avancer le langage dans la bonne direction.

On notera par exemple la création en 2012 de composer qui est un gestionnaire de paquet qui permet de télécharger une librairie ainsi que ses différentes dépendances (jusqu'alors il fallait télécharger manuellement les librairies que l'on souhaitait utiliser). Le PSR permet aussi d'améliorer l'interopabilité entre les Frameworks en proposant des règles de formatage mais aussi des interfaces à implémenter pour les différents composants (Request, Response, Container...).

La vie de PHP a été menacée lors du développement de la version 6.0 de PHP qui s'est avéré chaotique et qui a mis en pause l'avancée de PHP pendant un petit moment. Heureusement, la sortie en 2015 de PHP 7.0 a permis de faire avancer PHP avec une grosse amélioration en termes de performance mais aussi l'apparition de typage scalaire pour les paramètres de fonction, ce qui permet de grandement améliorer l'organisation du code.

Enfin, l'écosystème autour de PHP continue de se développer avec la sortie de nouvelle version des Frameworks tel que Symfony 4 en 2017 et Laravel 5.6 en 2018.

Donc PHP c'est si mal que ça ?

Donc PHP n'est pas forcément le meilleur langage de programmation, ce n'est pas forcément le langage le plus beau, ce n'est pas forcément non plus le langage le plus performant, mais c'est un langage qui est extrêmement efficace par rapport aux besoins pour lesquels il a été conçu. Le problème, c'est qu'aujourd'hui ces besoins ont changés et sont plus variés. On n'a plus aujourd'hui simplement besoin de générer une page HTML lors d'une requête. Les applications sont devenues plus complexes et on a besoin de nouveaux outils pour gérer ces nouvelles situations (Websockets par exemple).

En tant que développeur, il est important de choisir le bon outil en fonction de la situation, et de ne pas chercher à utiliser encore et toujours le même langage quelque soit la situation. C'est pour cela qu'aujourd'hui, on voit de plus en plus de langages apparaître et devenir populaires. Ces nouveaux langages sont conçus par rapport à de nouveaux besoins et correspondent à certaines situations et cela ne veut pas forcément dire que PHP doit disparaître pour que ces langages existent.
Par exemple il est tout à fait possible d'utiliser PHP pour la partie Web/HTML de votre application tout en ayant un autre langage de programmation pour d'autres parties (par exemple vous pouvez tout à fait générer vos pages Web en utilisant PHP et faire cohabiter un serveur NodeJS).

Au final, l'important est d'être productif avec l'outil que l'on a choisi.