Manual:Coding conventions/PHP/fr

Cette page décrit les conventions de codage utilisées pour les fichiers de la écrits en PHP. Voir aussi les qui s'appliquent à tous les langages de programmation, y compris PHP. Si vous désirez un résumé des éléments à vérifier lorsque vous faites vos validations (submit), voyez la.

Pour aider les développeurs à corriger leur code du point de vue répartition des espaces, il existe l'outil stylize, qui vérifie la syntaxe réellement et ajoute les espaces aux endroits nécessaires; cet outil est également disponible via un interface web. Il est recommandé de l'exécuter avant de valider les fichiers dans Git.

Les règles pour PHP_CodeSniffer sont aussi disponibles. Pour plus d'informations, voir. Le dépôt Git  contient les paramètres de PHP_CodeSniffer pour le code MediaWiki.

Espaces
MediaWiki encourage un style bien structuré au niveau des espaces pour une lisibilité optimale.

Indenter avec des caractères de tabulation et non pas en mettant des espaces. Limiter les lignes à 120 caractères (en portant la largeur de tabulation à 4 caractères).

Placez les espaces de chaque côté des opérateurs binaires, par exemple :

Placez les espaces à côté de l'intérieur des parenthèses, sauf si elles sont vides. Ne mettez pas d'espace après un nom de fonction.

Placez les espaces à l'intérieur des crochets lorsque vous déclarez un tableau, sauf si le tableau est vide. Ne mettez pas d'espace dans les crochets lorsque vous accédez aux éléments d'un tableau.

Les structures de contrôle telles que, , , , , ainsi que le mot clé , doivent être suivies d'un espace :

Lorsque le 'cast' est appliqué sur un type, ne mettez pas d'espace à l'intérieur ni après l'opérateur cast :

Dans les commentaires, il doit y avoir un espace entre le caractère (ou ) et le commentaire lui-même.

Pour aider les développeurs à corriger le code du point de vue de l'emplacement des espaces, il existe l'outil stylize qui ajoute automatiquement des caractères d'après les conventions PHP. Cet outil est disponible via l'interface web.

Opérateur ternaire
Le peut être utilisé à profit si les expressions sont très courtes et triviales :

Toutefois, si vous envisagez une expression multiligne avec un opérateur ternaire, utilisez plutôt un bloc. N'oubliez pas que l'espace disque n'est pas cher, que la lisibilité du code est primordiale, if est en anglais mais  ne l'est pas. Si vous utilisez une expression ternaire sur plusieurs lignes, le point d'interrogation et les deux points doivent figurer au début des deuxième et troisième lignes et non à la fin des première et deuxième (contrairement à la convention JavaScript de MediaWiki).

Depuis que MediaWiki nécessite PHP ou ultérieur, l'utilisation du shorthand ternary operator (opérateur ternaire  ) aussi connu sous le nom d'opérateur elvis et introduit en PHP 5.3, est autorisée.

Depuis PHP 7.0, l'opérateur de fusion nul est également disponible et peut remplacer l'opérateur ternaire dans certains cas d'utilisation. Par exemple, au lieu de :  vous pouvez écrire ceci :

Chaînes de caractères
Il est recommandé d'utiliser les apostrophes simples dans tous les cas où elles sont équivalentes aux doubles. Le code utilisant des guillemets simples est moins sujet aux erreurs et plus facile à relire, car il ne peut pas contenir accidentellement de séquences d'échappement ni de variables. Par exemple, l'expression régulière nécessite une barre oblique inverse supplémentaire, ce qui la rend légèrement plus confuse et source d'erreurs que. De même, pour les personnes utilisant les claviers qwerty US/UK, ils sont plus faciles à taper car ils évitent d’appuyer sur la touche Maj.

Néanmoins, n'ayez pas peur d'utiliser la fonctionalité PHP d'interpolation des chaînes à double apostrophes :

Ceci a des caractéristiques de performance quelque peu meilleures que l'équivalent utilisant l'opérateur de concatenation '.' (dot), et c'est aussi plus joli.

Les chaînes de style Heredoc ('Here document' ou document en ligne) sont parfois utiles :

Certains auteurs aiment utiliser END comme balise de fin, qui est également le nom d'une fonction PHP.

Fonctions et paramètres
Evitez de passer un trop grand nombre de paramètres aux fonctions at aux constructeurs :

Il devient rapidement impossible de se souvenir de l'ordre des paramètres et vous finirez inévitablement par coder toutes les valeurs par défaut des appelants pour personnaliser un paramètre à la fin de la liste. Si vous êtes tenté de coder une fonction comme celle-ci, envisagez plutôt de passer un tableau associatif de paramètres nommés.

En général, l'utilisation de paramètres booléens est déconseillée dans les fonctions. Dans, sans consulter la documentation de , il est impossible de savoir ce que ces paramètres sont censés indiquer. Il vaut bien mieux utiliser les constantes de classe et créer un paramètre de drapeau générique :



Ou pour que votre fonction accepte un tableau de paramètres nommés :



Essayez de ne pas modifier les variables au cours d'une fonction et évitez de modifier les paramètres transmis à une fonction (à moins qu'ils ne soient passés par référence et que c'est évidemment le but de la fonction).

Expressions d'assignement
Utiliser une assignation comme une expression est surprenant pour le lecteur et ressemble à une erreur. N'écrivez pas ce type de code :

L'espace n'est pas cher et vous écrivez rapidement, utilisez donc à la place :

Utiliser l'assignation dans une boucle est légitime pour l'itération :

Ceci est inutile dans le nouveau code; remplacez par :

Emprunts au langage C
Le langage PHP a été conçu par des personnes qui aiment le langage C et qui souhaitent importer des souvenirs de ce langage en PHP. Mais PHP a quelques différences importantes par rapport à C.

En C, les constantes sont implémentées en tant que macros de préprocesseur et sont rapides. En PHP, elles sont implémentées en effectuant une recherche dans une table de hachage à l'exécution avec le nom de la constante et sont plus lents qu'en utilisant simplement un littéral de chaîne. Dans la plupart des endroits où vous utiliseriez un ensemble de macros en C ou similaires à enum, vous pouvez utiliser des littéraux de chaîne en PHP.

PHP a trois littéraux spéciaux pour lesquels la combinaison des majuscules/minuscules n'est pas significative dans le langage (depuis PHP 5.1.3), mais pour lesquels notre convention utilise toujours les minuscules:, et.

Utilisez et non pas. Ils ont des significations différentes et subtiles:

Et le dernier a de piètres performances.

Syntaxe alternative pour les structures de contrôle
PHP offre une syntaxe alternative pour les structures de contrôle en utilisant des points-virgule ';' et des mots-clés tels que,  , etc. :

Cette syntaxe doit être évitée car elle empêche beaucoup d'éditeurs de texte de faire correspondre et de refermer automatiquement les accolades. Les accolades doivent être utilisées à la place :

Placement des parenthèses
Voir Manual:Coding conventions#indentation et alignement.

Déclarations de type dans les paramètres de fonction
Utilisez les déclarations de type et les déclarations du type retourné (type hinting) si nécessaire.

Notez que avant 7.4 PHP ne pouvait pas gérer la restriction/relaxation du type retourné dans les sous-classes.

Scalar typehints are allowed as of MediaWiki 1.35, following the switch to PHP 7.2 (T231710).

Use PHP 7.1 syntax for nullable parameters: choose

instead of

The former conveys precisely the nullability of a parameter, without risking any ambiguity with optional parameters. IDEs and static analysis tools will also recognize it as such, and will not complain if a non-nullable parameter follows a nullable one.

Nommage
Utilisez les minuscules alternées (lowerCamelCase) pour les noms de fonction ou de variable. Par exemple :

Utilisez des majuscules alternées (UpperCamelCase) pour les noms des classes :. Utilisez les majuscules avec des caractères souligné '_' pour les constantes de classe et les constantes globales :,. Les autres variables sont habituellement en minuscules ou en lowerCamelCase; évitez d'utiliser les soulignés dans les noms de variables.

Il existe aussi des préfixes utilisés à différents endroits :

Préfixes de fonctions

 * (fonctions wiki) – fonctions de niveau général, par exemple
 * (fonctions d'extensions) = les fonctions globales dans les extensions, bien que dans la plupart des cas, le style moderne déclare les fonctions d'accroche comme des méthodes statiques de classe, laissant peu ou pas de fonctions brutes de premier niveau ainsi nommées. (-- brion dans Manual_talk:Coding_conventions)

Préférez les phrases verbales : utilisez au lieu de.

Préfixes de variables

 * – variables globales, par exemple . Utilisez toujours ceci pour les nouvelles variables globales, de sorte qu'il soit facile de repérer les déclarations « » manquantes. Dans les extensions, le nom de l'extension doit être utilisé comme séparateur d'espace de noms. Par exemple,, et non.
 * Les déclarations globales doivent être au début d'une fonction pour que les dépendances puissent être déterminées sans avoir à lire l'intégralité de la fonction.

Il est courant de travailler avec une instance de la classe ; nous avons pour cela une convention de nommage qui permet de garder une trace de la nature du serveur auquel nous sommes connectés. Cela revêt une importance particulière dans les environnements répliqués, tels que Wikimedia et d’autres grands wikis; dans les environnements de développement, il n'y a généralement pas de différence entre les deux types, ce qui peut masquer des erreurs subtiles.


 * – un objet  pour l'écriture (une connexion maître)
 * – un objet  pour la lecture indépendante des accès concurrents (cela peut être un esclave en mode lecture seule, discrètement derrière l'état maître,  donc n'essayez jamais d'écrire dans la base de données avec, ou essayez d'obtenir une réponse d'« autorisation » pour les requêtes importantes comme les droits d'accès et les états bloqués)

Vous encore pouvez trouver ce qui suit dans du code ancien, mais pour du nouveau code, cela n'est pas recommandé :


 * – Variables de session, par exemple
 * – Variables de cookies, par exemple
 * – Variables postées (envoyées par les champs de formulaire), par exemple
 * – variables membres d'objets : . Ceci n'est pas du tout recommandé dans le nouveau code, mais essayez de rester cohérent à l'intérieur d'une même classe.

La fonction ne doit être utilisée pour ignorer les erreurs. Sinon utilisez simplement  (conversion booléenne).

Cas d'utilisation courant : clés de configuration booléennes optionnelles valant 'false' par défaut.
 * essentially does.
 * Méfiez-vous des pièges des conversions booléennes.
 * Cela supprime les erreurs concernant les propriétés et les variables non définies. Si vous souhaitez uniquement tester les non définis, utilisez . Si vous souhaitez uniquement tester les valeurs « vides » (par exemple, false, zéro, tableau vide, etc.), utilisez.

N'utilisez pas pour tester. L'utilisation de dans cette situation pourrait entraîner des erreurs en masquant les noms de variables mal orthographiées. Au lieu de cela, utilisez.

Conversion booléenne

 * N'utilisez pas  ni  pour tester si une chaîne ou un tableau est vide, car PHP considère   comme 'false' – mais   est un titre valide et un nom d'utilisateur valide dans MediaWiki. A la place, utilisez   ou.
 * Etudiez les règles à propos de la conversion en booléen. Faites attention quand vous convertissez des chaînes en boléens.

Autre

 * L'opérateur '+' des tableaux ne renumérote pas les clés des tableaux indexés numériquement, donc . Si vous voulez renuméroter les clés, utilisez :
 * Assurez-vous que vaut  . Ceci vous notifiera s'il existe des variables non définies et des autres pièges subtils que PHP ignore. Voir aussi.
 * Lorsque vous travaillez avec un fichier PHP pur (c'est à dire pas un modèle HTML), omettez les balises  fermantes. Ces balises causent souvent des problèmes avec les espaces de fin et les messages d’erreur en-tête déjà envoyés (voir 17642 et http://news.php.net/php.general/280796). La convention, dans le contrôle de version, pour les fichiers est qu'il ont généralement une nouvelle ligne à la fin du fichier (que les éditeurs peuvent ajouter automatiquement), ce qui déclencherait alors cette erreur.
 * N'utilisez pas la syntaxe introduite en 5.3. PHP a peut-être introduit la fonctionnalité, mais cela ne signifie pas que nous devons l'utiliser.
 * Si vous rencontrez un tableau, ne le passez pas par référence sauf si vous le devez. Et même, faites attention des conséquences (voir http://www.king-foo.be/2010/10/php-quirks-passing-an-array-by-reference/).
 * PHP vous permet de déclarer des variables statiques même au sein d'une méthode non statique d'une classe. Cela a conduit à des bugs subtils dans certains cas, car les variables sont partagées entre les instances. Là où vous n'utilisez pas une propriété, n'utilisez pas non plus de variable statique.

Opérateurs d'égalité
Faites attention avec les opérateurs de comparaison à double signe égal. Le triple-égal est généralement plus intuitif et doit être préféré, à moins que vous ayez une raison particulière d'utiliser le double-égal.


 * est vrai (!)
 * est vrai (!)
 * est faux
 * Pour vérifier que deux scalaires que vous supposez numériques sont égaux, utilisez, par exemple  est vrai.
 * Pour vérifier que deux variables sont de type 'string' et représentent la même séquence de charactères, utilisez, par exemple  est faux.

Watch out for internal functions and constructs that use weak comparisons; for instance, provide the third parameter to, and don't mix scalar types in   constructs.

Do not use Yoda conditionals.

Précision des nombres JSON
JSON utilise le système des types JavaScript, donc tous les chiffres sont représentés comme des nombres IEEE 64bits à virgule flottante. Cela signifie que plus les nombres deviennent grands, plus ils perdent en precision, jusqu'au point de où vous ne pouvez plus les différencier : les nombres au delà de 2^52 ont une précision inférieure à ±0,5 et donc un entier très grand peut se transformer en un nombre différent. Pour éviter ce problème, représentez les nombres entiers potentiellement très grands, par des chaînes en JSON.

Ne pas utiliser la construction lors de la sérialisation
Le mécanisme de sérialisation intégré de PHP (les fonctions  et  ) ne doivent pas être utilisées pour l'enregistrement des données (ou leur lecture) en dehors du processus actuel. A la place, utilisez la sérialisation basée sur JSON (néanmoins, faites attention aux pièges). Ceci est la règle établie par la RFC T161647.

La raison est double : (1) les données sérialisées avec ce mécanisme ne peuvent pas être désérialisées de manière fiable avec une version ultérieure de la même classe. Et (2), des données sérialisées spécialement construites peuvent être utilisées pour exécuter du code malveillant, ce qui pose un risque grave pour la sécurité.

Quelques fois, votre code ne va pas contôler le mécanisme de sérialization, mais utilisera une bibliothèque ou un pilote qui lui l'utilisera de manière interne. Dans de tels cas, il faut procéder par étapes pour réduire les risques. Le premier problème mentionné ci-dessus peut être évité en convertissant toute donnée en des tableaux ou des objets simples anonymes avant la sérialisation. Le deuxième problème peut éventuellement être résolu en utilisant la fonctionnalité de liste blanche introduite par PHP 7 pour la désérialisation.

Commentaires et documentation
Il est essentiel que votre code soit bien documenté afin que les autres développeurs et les correcteurs de bogues puissent facilement naviguer dans la logique de votre code. Les nouvelles classes, méthodes et variables membres doivent inclure des commentaires fournissant une brève description de leurs fonctionnalité (sauf si cela est évident), même si elles sont privées. En outre, toutes les nouvelles méthodes doivent documenter leurs paramètres et renvoyer des valeurs.

Nous utilisons le style de documentation Doxygen (il est très similaire à PHPDoc pour le sous-ensemble que nous utilisons) pour produire une documentation générée automatiquement à partir des commentaires du code (voir Manual:mwdocgen.php). Commencez un bloc de commentaires Doxygen avec, au lieu du formatage de style Qt. Les commandes structurelles de Doxygen commencent par. (utilisez pour le caractère d'échappement plutôt  que   – les deux styles sont acceptés dans Doxygen, mais pour raison de compatibilité arrière et avant, MediaWiki a choisi le style   ). Ils organisent la documentation générée (en utilisant ) et en identifiant les auteurs (en utilisant les balises  ).

Ils décrivent une fonction ou une méthode, leurs paramètres (en utilisant ), et ce qu'elles retournent (en utilisant  ). Le format pour les paramètres est :

@param type $paramName Description of parameter

Si un paramètre peut avoir plusieurs types, séparez-les avec le caractère pipe '|', par exemple :

Continuez les phrases appartenant à une annotation sur la ligne d'après, indentée avec un espace supplémentaire.

Pour chaque interface publique (méthode, classe, variable, peu importe) que vous ajoutez ou modifiez, fournissez une balise , ainsi les personnes qui reprendront le code via cet interface sauront qu'ils rompent la compatibilité avec les anciennes versions du code.

FIXME signifie généralement que quelque chose est mauvais ou cassé. TODO signifie que des améliorations sont nécessaires. cela ne signifie pas nécessairement que la personne qui ajoute le commentaire va le faire. HACK signifie qu'une solution rapide, mais inélégante, maladroite ou autrement sous-optimale, à un problème immédiat a été apportée, et qu'une réécriture plus complète du code devrait éventuellement être effectuée.

Entêtes des fichiers source
Afin d'être compatible avec la plupart des licences, vous devez avoir quelque chose de similaire à ce qui suit (spécifique aux applications GPLv2) au début de chaque fichier source.

Balises Doxygen
Nous utilisons les annotations suivantes reconnues par Doxygen. Utilisez-les dans cet ordre, par mesure de cohérence :

Niveau du fichier :
 * @file
 * @ingroup
 * @author

Classe, membre de classe, ou membre global :


 * @todo
 * @var
 * @deprecated
 * @class
 * @see
 * @since
 * @param
 * @return
 * @throws
 * @private

Annotations de test
Dans les tests, nous utilisons entre autres les annotations suivantes. Ce n'est pas simplement de la documentation, elles ont un sens pour PHPUnit et ont un impact sur l'exécution du test.


 * @depends
 * @group
 * @covers
 * @dataProvider
 * @expectedException
 * @expectedExceptionMessage

Intégration
Il existe dans le code MediaWiki quelques éléments de code destinés à être autonomes et facilement portables vers d'autres applications. Bien que certains d’entre eux existent maintenant sous la forme de bibliothèques séparées, d'autres restent dans l’arborescence source de MediaWiki (par exemple les fichiers de ). En dehors de ceux-ci, le code doit être intégré au reste de l'environnement MediaWiki et doit permettre à d'autres domaines de la base de code de s'y intégrer en retour.

Visibilité
Rendez les méthodes 'public', 'protected', ou 'private' (selon le rôle de la méthode). Réfléchissez : il ne s'agit pas de rendre tout 'public' !

Objets globaux
N'accédez pas directement aux superglobales PHP, , etc. utilisez  à la place; il existe diverses fonctions selon le type de valeur que vous souhaitez. Vous pouvez obtenir une requête à partir du  le plus proche, ou  si cela est absolument nécessaire. De même, n’accédez pas directement à ; utilisez si vous voulez obtenir l'adresse IP de l'utilisateur actuel.

Méthodes statiques et propriétés
Les méthodes statiques et les propriétés peuvent être utilisées en PHP, mais faites attention lorsque vous héritez de faire la différence entre les mots-clé  et. va toujours faire référence à la classe où il a été défini, tandis que  va faire référence à la sous-classe particulière qui l'a invoqué. Voir la documentation PHP sur la résolution statique à la volée (Late Static Bindings) pour plus de détails.

Classes
Encapsulez votre code dans une classe orientée objet ou ajoutez des fonctionnalités aux classes existantes; n'ajoutez pas de nouvelles fonctions ni variables globales. Essayez de faire attention à la distinction entre les classes 'backend', qui représentent des entités dans la base de données (par exemple,,  ,  ,etc.) et les classes 'frontend', qui représentent des pages ou des interfaces visibles pour l'utilisateur ( ,  ,  , etc. . Même si votre code n'est pas clairement orienté objet, vous pouvez le placer dans une classe statique (par exemple,   ou  ).

En raison de l'absence de méthodes et de membres de classe privés dans PHP 4, le code anciens sera marqué avec des commentaires tels que pour indiquer l'intention; respecter cela comme si c'était imposé par l'interpréteur.

Marquez le nouveau code avec des modificateurs de visibilité adaptés, y compris si c'est le cas, mais n'ajoutez jamais de visibilité à du code existant sans vérifier, tester et refactoriser si nécessaire. Il est bon d'éviter les modifications de visibilité sauf si vos modications cassent de toutes manières, le fonctionnement précédent de la fonction.

Gestion des erreurs
In general, you should not suppress PHP errors. The proper method of handling errors is to actually handle the errors.

For example, if you are thinking of using an error suppression operator to suppress an invalid array index warning, you should instead perform an check on the array index before trying to access it. When possible, always catch or naturally prevent PHP errors.

Only if there is a situation where you are expecting an unavoidable PHP warning, you may use PHP's operator. This is for cases where:


 * 1) Il est impossible d'anticiper l'erreur qui va arriver, et
 * 2) Vous envisagez de gérer l'erreur de manière appropriée une fois qu'elle est arrivée.

We use PHPCS to warn against use of the at-operator. If you really need to use it, you'll also need to instruct PHPCS to make an exemption, like so:

An example use case is opening a file with. You can try to predict the error by calling  and , but unlike  , such file operations add significant overhead and make for unstable code. For example, the file may be deleted or changed between the check and the actual  call (see TOC/TOU).

In this case, write the code to just try the main operation you need to do. Then handle the case of the file failing to open, by using the  operator to prevent PHP from being noisy, and then check the result afterwards. For  and , that means checking for a boolean false return, and then performing a fallback, or throw an exception.

Exceptions that indicate programming errors should be one of the exceptions that ship with PHP or a more specific subclass, while exceptions that indicate errors that are relevant to the end user should be an ErrorPageError or one of its subclasses.

AtEase
For PHP 5 and earlier, MediaWiki developers discouraged use of the  operator due to it causing unlogged and unexplained fatal errors (r39789). Instead, we used custom  and   methods from the  library. The reason is that the at-operator caused PHP to not provide error messages or stack traces upon fatal errors. While the at-operator is mainly intended for non-fatal errors (not exceptions or fatals), if a fatal were to happen it would make for a very poor developer experience.

In PHP 7, the exception handler was fixed (example) to always provide such errors, including a stack trace, regardless of error suppression. In 2020, use of AtEase started a phase out, reinstating the at-operator. (T253461)