Déterrer le cadavre d’un troll : Non, PHP n’est pas simple


Sujet traité 100 fois mais c’est à vocation thérapeuthique.

Quand on demande pourquoi je préfère Python à PHP, je réponds souvent que Python est beaucoup plus simple à utiliser. C’est généralement le moment où tout le monde me répond que PHP est justement un langage qui a eu du succès parcequ’il était simple.

Faux.

PHP a eu du succès parcequ’il a une excellente doc, des tutoriaux partout sur le net, et une méthode de déploiement facile proposée pour la plupart des hébergeurs.

Le code lui-même, n’est pas simple du tout. Prenez par exemple la fonction de base pour ouvrir un fichier, fopen().

@fopen('http://example.com/not-existing-file', 'r');

Savez vous ce que ce code va faire ?

Si PHP a été compilé avec --disable-url-fopen-wrapper, ça ne marchera pas. “Ne marchera pas” veut-il dire retourner null ou lever une exception ? Aucune idée, la doc ne le dit pas. De toute façon cette option est retirée avec PHP 5.2.5, et nous sommes en PHP 5.3.10 sur la plupart des distribs. Sauf sur la plupart des hébergeurs…

Si allow_url_fopen est désactivé dans php.ini, ça ne marchera pas non plus. Aucune idée de pourquoi.

Grâve à ce merveilleux “@”, le warning en cas de fichier n’existant pas ne sera pas affiché pas vrai ?

Sauf bien sur si scream.enabled est activé dans le php.ini ou manuellement avec ini_set.

A condition que le niveau error_reporting soit ajusté en conséquence.

Mais alors sa sortie dépend du paramètre display_errors, lui même activable dans le php.ini ou par ini_set.

Et si par un hasard incroyable vous savez tout cela, savez-vous comment est configuré votre hébergeur ?

This is going to be legend…

Après il est vrai que l’écosystème de Python, lui, possède une richesse qui le rend complexe. et le déploiement n’est pas aussi simple qu’avec PHP. D’ailleurs, je ne prétend pas qu’on ne puisse pas coder d’excellents produits avec PHP. Mais ce n’est pas grâce à la prétendue simplicité du langage (Ruby et même Javascript sont plus simples).

Le Web utilise par exemple massivement le JSON. Mais saviez-vous que json_decode retourne null en cas d’erreur de décodage ? Ce qui est aussi une valeur de retour de décoage de JSON valide, vous forçant donc à a vérifier json_last_error à chaque appel.

Je vous passe l’habituelle critique de la surabondance de fonctions PHP pour faire des choses similaires, mais avec des noms complètement à l’arrache (chercher du texte: ereg, eregi, mb_ereg, mb_eregi, preg_match, strstr, strchr, stristr, strrchr, strpos, stripos, strrpos, strripos, mb_strpos, mb_strrpos) ainsi que de l’inutilité totale du signe == ("foo" == true, et "foo" == 0 mais true != 0).

Par contre, quelqu’un pourrait m’expliquer pourquoi les noms des variables sont sensibles à la casse, mais PAS ceux des fonctions et classes ?

Et vous voulez vérifier qu’une variable est vide ou n’existe pas ? empty() est là pour ça ! Sauf que empty($var) marche, mais empty($var1 || $var2) lève une exception.

…wait for it…

En parlant d’exception, amusons nous un peu avec la gestions des erreurs:

  • la généricité c’est pas pour demain: curl_error, json_last_error, openssl_error_string, imap_errors, mysql_error, xml_get_error_code, bzerror, date_get_last_errors
  • on autorise à rendre les erreurs silencieuses avec ‘@’ (wtf ?)
  • pas de stack trace. Un bug ? Démerde toi. Le langage est en typage faible, tu vas t’amuser !
  • :: est nommé T_PAAMAYIM_NEKUDOTAYIM et <<, T_SL, et la première fois qu'on le voit dans un message d'erreur, ça fait tout drôle. Il vaut mieux ne pas être déconnecté.
  • E_ALL inclue toutes les catégories d'erreur. Sauf E_STRICT. Quelqu'un sait à quoi sert E_STRICT ?
  • on a pas le droit de lever une exception dans __toString ! Si on le fait, PHP balance une erreur fatale, et ...
  • ... les erreurs fatales ne peuvent pas être gérées dans un try/catch. Et de toute façon il n'y a pas de clause finally.

Et quand PHP évolue, au lieu de corriger ce bordel, on rajoute une couche !

Par exemple, PHP est faiblement typé. Sauf qu'on peut maintenant forcer le type des paramètres d'une fonction en donnant ce qu'on appelle des type hints. Sauf qu'on qu'on ne peut pas choisir "string" ou "int" ni aucun type de base pour cela. Sauf que les fontions de les bibliothèques standards elles, le font sans problème. Il faut donc utiliser une classe que l'on fait soit même. Sauf que les "type hints" acceptent une classe non déclarée comme type (faute de frappe mon ami...). Sauf que dans ce cas on ne peut passer aucun argument à la fonction. Absolument aucun.

Par contre, mettre des arguments nommés pour les fonctions, ça, on ne le rajoute pas. Ca rendrait le code plus bordélique, et il faut garder le langage simple. C'est d'ailleurs, j'en suis certain, au nom de cette simplicité que mktime a pour ordre d'arguments: heure, minute, seconde, mois, jour, année.

... dary !

Heureusement il y a des fonctions cachées qui font que PHP est vraiment un langage pour faciliter la vie du débutant:

preg_replace avec le flag /e prend la chaine, effectue le remplacement, et ensuite fait un eval() dessus !

scandir retourne une liste de fichiers dans un dossier, mais pas dans l'ordre du dossier. Non, ce serait pas fun. Il les retourne dans l'ordre alphabetique, ou l'inverse si on lui passe un argument. Ce qui est logique, puisque PHP est bien connu pour manque de fontions de tris: array_multisort, arsort, asort, ksort, krsort, natsort, natcasesort, sort, rsort, uasort, uksort, usort.

parse_str ne parse pas une chaîne, mais une "query string". Qu'il dump ensuite dans l'espace de nom local. A moins qu'on lui passe un array à populer. Mais dans tous les cas la fonction ne retourne rien.

gzgetss parse les lignes d'un fichier *.gz et en retire les ligne HTML. Indispensable dans la vie de tous les jours, ça valait le coup d'en faire une fonction built-in. Hier encore je me demandais comme j'aillais rajouter cette opération à toutes mes vues Django.

php_uname retourne l'OS courrant, mais en cas d'échec, il retourne silencieusement l'OS sur lequel il a été compilé.

Et les arrays... Cette structure de donnée magique qu'on aime tant quand on commence à programmer. Ca fait tout, tout je vous dis !

Les arrays sont une combinaisons de lists, ordered hashes, ordered sets et sparse lists. Là ou c'est amusant, c'est quand on tente de les comparer:

array_diff(array("marc" => 12, "alice" => 23),
           array("marc" => 23, "alice" => 12));

Quel comportement vérifier, celui d'une liste, d'un set ou d'un mapping ?

Ici la réponse est un set, ce qui fait que les deux arrays sont considérés comme égaux.

Par contre:

array("foo", "bar") != array("bar", "foo")

Et:

array("foo" => 1, "bar" => 2) == array("bar" => 2, "foo" => 1)

Tient, tant qu'on est dans la prédictibilité de comportement. Puisque PHP est un langage simple, quelqu'un peut me prédire ce que ça fait ?

php > $a = null;
php > $a++;
php > echo $a;

Non ?

Ben ça a affiche 1. Si, si.

Mais comme on aime bien la congruence chez Zend:

php > $a = null;
php > $a--;
php > echo $a;

Ça n'affiche rien.

Et pour finir sur une petite note de sécurité spécial noob: include accepte une url en paramètre.

J'ai passé des années à coder en PHP. J'ai vu du code très propre faire des choses très belles. Ce n'est pas grâce au langage, mais en dépit de lui.

Je suis heureux que le langage ai eu un tel succès. Il a permis au Web de devenir ce qu'il est. Il est temps maintenant de passer à autre chose.

29 thoughts on “Déterrer le cadavre d’un troll : Non, PHP n’est pas simple

  • Baronsed

    Déjà testé Opa ? C’est un dialecte d’Ocaml pour le web. Compilable.
    Un même langage côté client et côté serveur. Pas besoin d’installer de serveur, il est intégré. Ça évite de déployer 5 technos quoi :)

  • Sam Post author

    Opa est apparu en 2010, alors que:

    Python: 1990
    Php: 1994
    Ruby et JS: 1995

    Même si Opa était en tout points supérieur à tous ces langages, 15 ans de tests sur le terrains par des milliers de développeurs et autant de remplissage de tuto/doc/forum ont une valeur bien supérieur à tout le reste.

    Sans compter qu’Opa intègre le serveur Web, donc il lui manque aussi le retour d’expérience (et les modules) de Apache, lighttpd, nginx.

    Et évidement Opa se veut son propre framework, ce qui l’oppose aux Django, Rails et Symfony qui proposent des ORMS, libs de form, de caching, qui représentent une somme de travail gigantesque que les quelques dev d’OPA ne pourront pas matcher avant des lustres.

    Ca ne veut pas dire qu’il ne faut pas donner sa chance aux nouvelles technos, mais je ne le mettrais pas en prod avant des années.

  • All-o

    full disclosure: Je programme en tant qu’amateur. J’ai pratiqué le PHP (10 ans), le python (3 ans), le java (3 ans) ainsi que divers autres langages en diletante.

    Ouuh le vieux troll poilu. J’avoue que je suis un peu déçu de trouver un article aussi “faible” ici. Certains grief cités sont pas loins de la mauvaise foi. Un petit phpinfo() donnera toute la config par exemple.

    J’ai essayé de faire un petit client torrent en python, eh bien j’en ai bavé. Module1 dispo que sous 2.6, module2 dispo que sous 2.7 et 3.3 mais qui bug sous 3.3.2. Essayez de faire un client soap en python 3? bonne chance.

    Pour autant je ne dis pas que python est nul et complexe. Il y a toujours un moment ou il y a des comportements inutiles ou illogiques, des fonctions en doublon ou qui manquent, des erreurs louchent difficiles a débuger, etc… et ce, quel que soit le langage utilisé.

    En bref je vois pas l’intéret de dire “boouh untel langage est pas bien”. En fait tous les langages sont pourris, ils le sont juste un peu moins selon la situation et l’expérience du programmeur. Quel est l’intéret de dire qu’une poule est inutile car elle ne peut pas voler?

  • Sam Post author

    Ce n’est pas le propos de l’article. Le titre c’est “Non, Php n’est pas simple”. Pas “Php est inutile” ou “Php c’est caca”.

    Mon propos n’est pas “Python c’est mieux que PHP, Na na nère” (même si je le pense), mais “Php est difficile, c’est pour cela que je préfère Python”.

    Car oui, faire un client torrent en Python sera toujours plus simple que de le faire en PHP (puisque vous aimez SO):

    http://stackoverflow.com/questions/4575975/pure-php-torrent-client

    L’avantage de PHP est son abondance de bonne doc, de tutos, même en français. PHP a tout de suite visé le Web (bien avant les frameworks pour les autres langages, ce qui rendait la programmation Web en Python/Ruby très désagréable), et c’est la raison de son succès.

    Ca ne change rien au fait que Php est un langage difficile: faire une grosse application et la maintenir en PHP est très dur. Faire autre chose que du Web en Php demande beaucoup d’effort.

    Je ne tamponnerai pas “troll” les commentaires sur cet article, car vous avez raison, je l’ai quand même bien cherché :)

  • Alex

    @Sam je suis développeur web professionnel, spécialisé dans le développement frontend (pas l’intégration hein … mais le développement de l’expérience utilisateur etc. Car faire de l’HTML et de la CSS ce n’est pas développer car ce ne sont pas des langages de programmation).

    Développer une grosse application n’est pas dur du tout il suffit de se donner les moyens nécessaires. Ne pas utiliser de framework solide pour un grosse plateforme est un suicide. Et là je parle pas des petits frameworks que sont CakePHP, Code Igniter etc. Qui sont comiques 5 minutes et inutiles le reste de la vie d’un site qui se respecte. Mais bien de frameworks tels que Zend, ou mieux, Symfony (la deuxième version est une tuerie si on prend le temps de l’exploiter).

    Et pour ton information Symfony reprend des concepts de Django (surtout il me semble au niveau du moteur de templates.

    Maintenant à mes yeux, les faiblesses PHP sont sa syntaxe qui peut être très / trop verbeuse, sa retro-compatibilité un peu lourde des fois, mais surtout, le faite de faire croire à tout le monde qu’il est facile de faire un site Internet à cause de l’écosystème qui l’entoure.

    Et oui, je me permet d’en mettre une couche. Pour moi PHP ne peut servir qu’à fournir des pages web ou des services web. Il a été utilisé dés son départ dans cette optique. Je l’ai jamais utilisé pour autre chose, et je ne l’utiliserai jamais. Si je dois développer une solution intégrée demandant des ressources autres que le web je me tournerai vers Python ;)

  • Sam Post author

    Je suis initialement développeur PHP, et je suis passé par Symfony :-) La version 2 est effectivement beaucoup plus sympas, moins lourde.

  • All-o

    Mon idée était surtout de dire que n’importe quel langage peut être considéré commme “pas simple”, que c’est surtout une question de point de vue et de situation.

    Je suis tout à fait d’accord sur le fait que php est limité, faire autre chose que du web avec relève du casse-tête. C’est d’ailleur la raison pour laquelle j’ai commencé a apprendre d’autres langages. Par contre pour faire du web je le trouve très simple, adapté et doccumenté. Après les goûts et les couleurs…

  • Sam Post author

    Je comprends.

    Cet article est un coup de gueule dû à deux choses:

    – je suis formateur, et j’ai formé en PHP et en Python
    – je suis ergonome

    La double casquette formateur et ergonome me rend très sévère sur PHP. Ca ne veut pas dire que je ne le serais pas avec le C ou Erlang ou Lisp.

    Ce qui me déplait, c’est qu’on vende PHP parcequ’il est facile.

    D’expérience (sans même parler du développement), il est plus facile de former une personne qui n’y connait rien en programmation en Python qu’en PHP.

    Et d’un point de vue d’ergonome, la charge cognotive liée à la lecture du code PHP est (et je parle de chiffres mesurables), bien supérieure.

  • serialk

    Ou alors tu aurais juste pu donner le lien vers PHP : A fractal of Bad Design ? Ridicule.

  • serialk

    Ne détourne pas ce que je dis,pourquoi as tu (mal) traduit un article sans le citer une fois ? Et les autres points étaient trop techniques pour toi ? C’est tellement pitoyable, j’espère que tes autres articles sont pas aussi attention-whore oriented, parce que je trouve ça grave qu’autant de gens te prennent au sérieux.

  • desfrenes

    “un framework PHP qui me parait avoir plus de sens que les autres”

    C’est une blague ? Je la trouve excellente. Sinon, met un coup de botte dans github et des trucs comme ça t’en verras tomber tous seuls.

    Certes, le site est joli.

  • Hippopodame hamac

    Pour aider le troll zombie à se réveiller, rien ne vaut un petit coup de langue de pute pleine de mauvaise bile avec des vérités non vérifiées issues de l’expérience de terrain des Pythonistas qui se marrent en regardant trimer leurs malheureux confrères.

    Si on avait appris aux intégrateurs à utiliser Python plutôt que Php, ils seraient devenus des développeurs, et le web ne serait pas cet espace numérique surchargé de code instable et non testé.

    Bien-sûr Symfony c’est un énaurme progrès par rapport à des applications web développées avec Drupal ou autres CMS épouvantables, mais on formerait plus vite un “développeur Php” qui n’a jamais écrit une ligne de Python à Django qu’à Symfony. Quant à sa productivité, elle serait multipliée par dix, et encore je suis gentil.

    En fait Php c’est un monde d’initiés car le code est illisible, certaines fonctions avec des noms pas possibles font des trucs magiques qu’il faut connaître absolument car de toute façon c’est pas possible de déboguer. Et quand on entre dans un framework Php et bien c’est pareil, celui qui connait s’en sort à peu près, mais le débutant avec seulement 5 ans de Php dont 6 mois de Symfony passe des heures à chercher la doc ou des infos sur le web.

    Passer les trois quarts du temps à chercher de la doc et des astuces c’est compris dans le tarif développeur Php, c’est pour ça qu’il n’est pas cher payé.

    Mais si le développeur Php casse les prix, ce n’est pas son principal problème, car après son boulot pour compenser il pourrit le web d’astuces à deux balles.

    Pour sûr c’est pas la doc Php qui manque sur le web, mais chercher sur Google une page de référence pour résumer le langage “Php quick reference” vs “Python quick reference”, c’est un vrai challenge de geek qui ne dort jamais la nuit et qui profite peu de la vie.

  • Alain

    Tu évoques rapidement le déploiement sur php qui est plus simple. J’ai fait une pige en entreprise en bossant avec python et j’ai vraiment apprécié le language. Mais pour des projets persos ou dans ma nouvelle boîte je suis vite revenu la queue entre les jambes vers php rien que pour la rapidité avec laquelle on déploie sur Apache.
    Donc ma question : qu’est-ce que vous utilisez comme serveur web pour déployer du python, sur des sites grands public par exemple ?

  • Sam Post author

    @Alain: je crois que le déploiement avec Python mérite une article à lui tout seul. Mais en résumé, on utilise généralement gunicorn comme server wsgi et nginx en http proxy. C’est très facile à mettre en oeuvre, super robuste et rapide, mais mal documenté, et pas du tout dispo sur les hébergeurs mutualisés (donc uniquement sur serveur perso).

  • shaoner

    Perso j’aimerais bien aussi voir un article sur le deploiement d’un projet Django avec nginx par exemple. Mais surtout accompagne d’un “web git deploy” (en gros un script dans un hooks post-receive de gitolite) qui pourrait gerer un deploiement en testing, production, ou plus.
    Pour l’instant j’ai fait le mien pour ca, avec des settings dans django differentes selon le mode (testing, prod, new_feature) et son propre sous-domaine a chaque fois (sauf pour le site en prod) qui lui est le domaine principal.
    Mais voila, c’est pas forcement plaisant a faire :D et surtout j’aimerais m’abstraire de ce boulot pour me concentrer plutot sur l’application en elle-meme.

    • Sam Post author

      Ok pour l’article sur le déploiement (quand j’ai la foi, hein, c’est un gros morceau). Pour le reste, c’est plutôt un projet communautaire sur github qu’il faudrait.

  • t0w

    “Si allow_url_fopen est désactivé dans php.ini, ça ne marchera pas non plus. Aucune idée de pourquoi.”

    Hmmm.. à tout hasard parce que c’est sont rôle ? allow_url_fopen permet d’autoriser ou non le fait d’ouvrir des fichiers situés sur des serveurs différents de celui sur lequel est le script. /troll

    Mais sinon je suis bien d’accord bien que moi même développeur php depuis quelques années. Force est de reconnaitre que pas mal de choses demandent une certaine expérience pour être maitrisées.

    t
    0w

  • Guitoup

    Le gros poblème de PHP est en partie dans sa communauté, une grosse part est faite de bidouilleur, donc oui les forum sont pollués par des réponses pourries, et alors ? A nous de prendre du temps pour conseiller au mieux les débutants. Mon gros souci est plutôt du côté des “décideurs” du core PHP, au lieu de nous pondre une refonte de l’API avec de la cohérence, suppression des anciens boulets venant de PHP3/4, unicode (bordel!)…, non à la place il nous sorte des traits…des namespaces foireux… Je suis jaloux de la direction que prends Python avec la version 3, elle a le mérite de péter la rétrocompatibilité et de faire avancer les choses dans le bon sens ! A quand un PHP7 (vu que le 6 est mort-né) qui reprends tout ! Zut, crotte, saperlipoppette !

  • Xavier Combelle

    A propos de == en php c’est pas ce que tu prétends: c’est pire

     
    $ php5 --interactive
     
    var_dump("0e4"=="0e5");
     
    bool(true)

Comments are closed.

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.