Mise à jour le 13/11/2021
PSR-1: Basic Coding Standard

PSR-1: Basic Coding Standard

1. Introduction

Cette toute première PSR toujours valide, la bien nommée PSR-1(https://www.php-fig.org/psr/psr-1/) pose le décor : il est vivement recommandé lorsqu'on fait du PHP de faire du POO, cela ne semble par contre pas obligatoire (voir la conclusion).

2. Résumé des règles

* Les fichiers PHP doivent uniquement utiliser la balise <?php
* Les fichiers doivent uniquement être encodés en UTF-8 sans entête BOM
* Les fichiers doivent soit être déclaratifs (constances, classes, fonctions), soit être à effet de bord (modifie des fichiers, appels des services), jamais les deux en même temps
* Les namespaces et classes doivent respecter la convention de nommage de la PSR-4
* Les noms des classes sont en StudlyCaps
* Les noms des constantes de classes sont toujours en majuscule et espacé si besoin par des underscores.
* Les noms des méthodes doivent être déclarés en camelCase.

3. Les règles une par une

3.1 Les balises PHP

3.1.1 Une et une seule balise

Bien qu'il existe d'autres balises, une seule balise doit être utilisée, la balise <?php
La balise ?> ne doit pas être utilisée:
* Le code HTML est de toute manière toujours séparé du code PHP
* cela évite de laisser des caractères en fin de fichier interprété comme des caractères HTML

3.1.2 Exemple d'utilisation

Tous les fichiers .php de votre projet doivent commencer par cette ligne suivie d'un retour à la ligne :

<?php

3.2 UTF-8 sans BOM

D'où la nécessite d'écrire du code avec des outils dédiés (exit donc le wordpad de Windows par exemple).
Le BOM est une entête de fichier pratiquement invisible lorsque l'on code. Au moment de l'appel au serveur, ce caractère est le premier que le navigateur voit lorsqu'il pense récupérer le contenu de la page (avant donc le <!DOCTYPE ou <html>).
Comme ce caractère est en dehors de toute balise meta qui indiquerait l'encodage de la page, le navigateur va faire comme il souhaite puisqu'il considère que la page html n'est pas valide, tous les caractères sont alors affichés en non UTF-8.

3.2.1 Exemple d'IDE

Voici plusieurs outils qui ont la notion d'encodage et de BOM:
Sûrs :
* PHPStorm 2020.3
* Geany 1.36

Probables :
* NodePad++
* Visual Studio
* SublimeText
* Atom
* Eclipse

Peu probables :
* Wordpad
* Gedit
* Kate
* Mousepad
* Leafpad
* Pluma
* KWrite et Kedit
* Nedit/TEA ?

Certains outils de traitement de texte en ligne de commande n'injectent pas d'entête BOM :
* emacs (et XEdit)
* vim (et Gvim)
* nano

3.3 Fichiers purement déclaratifs ou à effet de bord (side-effect)

3.3.1 Fichier PHP avec effet de bords == PHP procédural

Si un fichier PHP, lors de son execution provoque ceci,on considère qu'il a des effets de bord :
* génèrer une sortie (avec echo, print_r et autres)
* lire, créer ou modifier un fichier (file_put_contents, fwrite et autres)
* modifier la configuration de PHP (set_ini)
* utiliser un require/include, interdit de toute manière en dehors des choses comme l'autoloader
* faire appel à un service externe (HTTP, FTP, n'importe quoi)
* génèrer des erreurs
* modifier des variables globales ou statiques

Ce qui est globalement très souvent le cas lorsque l'on fait du procédural, à moins de faire du code qui ne fait rien.

3.3.2 Fichier PHP sans effet de bords == PHP POO

En bref, un fichier déclaratif ne doit rien faire sauf déclarer, c'est à dire :
* tous les fichiers de classes/interfaces sont déclaratifs
* tous les fichiers PHP qui déclarent uniquement des fonctions (utilisation du mot clef function), des constantes (utilisation du mot clef define)

Cependant, il y a certaines ambiguités, aujourd'hui nous avons tendance à créer des classes de type Controller ou même Command.
Ces deux là remplacent dans le concept les fichiers de type command.php et index.php que l'on manipulait en non POO.

En d'autres termes, la PSR-1 est clairement du côté de l'usage de la POO. Les fichiers PHP de type procédurale sont à oublier dans le code source de votre application.

3.4 Une execution dépend forcément d'un fichier écrit en PHP procédural

Il ne faut pas penser qu'une application en PHP ne peut tourner qu'avec du POO vu que ce n'est que du déclaratif, car il y a forcément au moins dans votre projet un fichier quelque part écrit en procédural pour executer tout ce beau monde.
Ex: via composer 1.10, le fichier autoload.php est celui qui se charge d'executer tout ce petit monde.

Donc, pour faire simple et respecter cette règle :
* tous les fichiers PHP de votre projet sont en POO use/class/interface/namespace et sont donc déclaratif
* le seul et unique fichier de type side-effect est l'autoload, bien souvent géré par Composer ou par un autre Framework

/!\ ce qui est appelé effet de bord est le fait que la ligne s'execute, pas qu'elle soit utilisée dans une définition.
Par exemple, on peut très bien définir une méthode dans une classe qui ferait un appel à un service externe.
Mais le fait de charger cette classe ne doit effectivement pas executer la ligne en question, sauf si c'est demandé par un fichier executif.

3.4.1 Un fichier PHP == Une seule classe ou interface

Bien que dans sa cuisine interne d'optimisation, le framework que vous utilisez fait une fusion de toutes les déclarations. Lors du développement, il faut créer autant de fichier que de classe/interface.

3.5 L'autoloading

Fini le temps où les fichiers PHP sont importés dans son code via des require ou des include. Chaque fichier PHP doit déclarer en entête son namespace (cf la PSR-4 pour le nommage) et importer les autres fichiers via des use.
Il y a des exceptions : l'autoloader est le seul à pouvoir faire des includes, idem pour un système personnalisé de mise en cache du code PHP.

3.6 Nommage des classes

Le nom des classes et des fichiers de classe doivent être en StudlyCaps, c'est à dire que tous les mots sont reliés ensemble sans espace et commencent chacun par une majuscule.
Ex: SecurityController pour le nom de la classe et SecurityController.php pour le nom du fichier.

3.7 Nommage des constantes

Toutes les constantes doivent être définies dans des classes ou des interfaces.
En static car il n'est pas être nécessaire d'instancier la classe.

Pendant un temps la visibilité unique des constantes était public, on peut désormais changer cette visibilité.

3.7.1 Exemple de déclaration de constante

Voilà comment on peut définir des constantes :

<?php
namespace App;

class MyClass
{
    public static const MY_STRING_CONST = 'valeur';
    protected static const MY_BOOL_CONST = true;
    private static const MY_INT_CONST = 8;
    public static const MY_FLOAT_CONST = 8.08;
}

3.7.2 Exemple d'utilisation d'une constante dans un namespace commun

Voilà comment on peut appeler une constante public (ne pas oublier le use en entête) :

<?php
namespace App;

echo MyClass::MY_STRING_CONST;

3.7.3 Exemple d'utilisation d'une constante dans un namespace différent

Si la classe est dans un autre namespace, par exemple elle est déclarée dans la classe App\MyClass et est appelée en procédural dans le namespace Walt, il faut l'indiquer dans un use.
<?php
namespace Walt;

use App\MyClass;

echo MyClass::MY_STRING_CONST;

4. Conclusion : POO obligatoire ou non ?

Alors, est il possible de faire du PHP sans faire du POO en respectant la PSR-1 ? Je pense que la réponse est Oui.

Imaginons deux fichiers :
* index.php : uniquement du procédural (pas de définition), fait un require_once('lib.php');
* lib.php : uniquement des définitions de fonctions.

index.php :

<?php
require_once('lib.php');
myFunction();


lib.php :

<?php
function myFunction()
{
    // Peu importe, du code.
}


A priori, ce n'est pas de la POO mais cela respecte les différentes règles de la PSR-1.

On peut même aller plus loin en créant autant de librairies que l'on souhaite avec des noms plus judicieux et les injecter avec d'autres require.

La PSR-1 ne rend donc pas obligatoire la POO mais l'incite fortement vu que l'accent est fortement mis sur l'application de la PSR-4.