Le truc c'est que tu peux avoir la meilleure entreprise de construction qui soit, quand tu construis sur une fondation bâclée, tu gardes un résultat médiocre.
C'est typiquement le problème de PHP d'ailleurs. Regarde juste l'incohérence des API due à la rétrocompatibilité avec des modules faits à la va vite il y a 15 ans. Il est probable que ce soit le même bordel à l'intérieur car, si mes souvenirs sont bons, le moteur PHP n'a jamais été réécrit from scratch.
Juste quelques exemples :
- mysql_escape_string euuhh... non en fait mysql_real_escape_string, parce que la première est buggée et n'est gardée que pour le code legacy.
- strpos mais str_rot13. Conventions de nommage ?
- array_map($callback, înput) mais array_filter($input, $callback). D'ailleurs tant qu'on est là, t'as à peu près la moitié des fonctions de tableau qui commencent par array_. Les autres non. Parce que.
- On parlait du fameux opérateur == qu'il ne faut officiellement pas utiliser, mais lui préférer ===, sinon on crée des bugs bizarres et difficiles à débugger. Par exemple : TRUE == "truc" et "truc" == 0 mais TRUE != 0. L'opérateur de comparaison n'est pas transitif !
- Encore un autre avec ==, en PHP, "32k43d21fg" == "32z12xxx". En revanche, "032" != 032.
- Sur les types encore: 012 == 10, normal. Mais alors pourquoi 08 === 0 alors que 0a génère une erreur ?
- On rejoue ? 0b0+1 === 2. Oui monsieur.
- On rejoue avec les comparaisons ? L'opérateur === fonctionne différemment selon le type. Pour les objets, il compare l'identité de l'objet. Alors que pour les autres types il compare la valeur. Si tu veux comparer le type et la valeur, tu est obligé de faire ça : (is_object(a) || is_object(b) ? a == b : a === b)
- les conversions en (int) alors que le langage n'as pas de type int.
- Le typage dynamique n'est pas spécifié. D'ailleurs la conversion de type que tu obtiens avec certains opérateurs a changé d'une version à l'autre du moteur.
- Le comportement de certaines API dépend des options de compilation de PHP. Concrètement ça veut dire que pour savoir ce que fait un bout de code, tu dois aller consulter les options de compilation utilisées pour ton binaire de PHP.
- json_decode retourne le même résultat quand il rencontre une erreur que quand tu lui passes une donnée valide qui vaut null.
- strpos peut renvoyer 0 ou false, ce qui est une invitation au bug (if strpos()...)
- Saviez-vous que NULL == 0 et NULL < -1
- En PHP, "10" < "011". Il n'existe aucun moyen de le forcer à comparer les chaînes, il faut ajouter un caracatère en début de chaîne avant la comparaison pour contourner le problème : ("x" . A < "x" . B).
- PHP est sensible à la casse… mais pas trop. Les variables le sont, les fonctions ne le sont pas. Pourquoi ?
- Certaines exceptions ne peuvent pas être interceptées par un try catch. Par exemple new ClasseInexistante() tue le programme, même dans un bloc try catch.
- Il y a des circonstances où une erreur les paramètres du constructeur provoque l'invocation du destructeur. Toujours pas compris ni pourquoi ni comment. Depuis j'ai mis à jour mon PHP et ça ne le fait plus. Ça restera un grand mystère.
- Il y a un is_a et un instanceof (on note la naming convention une fois encore). J'ai toujours pas compris la différence exacte, mais ils ne font pas exactement la même chose. Oh et tu ne peux utiliser ni l'un ni l'autre pour tester si une variable est un entier. Pour ça il faut utiliser is_int.
- Dans le même registre, get_class($truc) renvoie le nom de la classe de $truc. Sauf si $truc est null. Dans ce cas ça fait quoi ? La réponse est drole, je vous laisse lire la doc.
C'est juste quelques exemples que j'avais noté à l'époque tellement ça me gonflait. Parce que les comparaisons et les chaînes en particulier m'ont bien saoulé à l'époque où je faisais des trucs avec PHP. Mais quand je vois comme c'est le bordel juste pour manipuler quelques chaînes dans un addon, j'ose pas imaginer ce que c'est quand tu commences à utiliser des modules plus compliqués. Tiens par exemple mysql, faut utiliser lequel des modules officiels intégrés à PHP ? mysql ? mysqli ? PDO ? Pourquoi il y a 3 modules officiels pour la même fonctionnalité ?