Bien maîtriser le langage de base de votre jeu web est essentiel pour savoir quels gameplay vous pouvez vous autoriser, et comment les implémenter.

$string[$n] vs $string{$n}

$string[$n] donne le n-eme octet d’une chaîne de caractères, alors que $string{$n} donne son n-eme carctère (en unicode ou UTF-8, certaines lettres prennent plusieurs octets). Privilégiez donc la 2e solution pour les string, et laissez la 1ere aux vrais tableaux (array).

Classes abstraites

Les abstract class sont très pratiques si vous vous en servez pour centraliser du code entre plusieurs classes, de façon similaire aux

trait
, qui sont toutefois moins structurés à l’usage (= cela tend à mettre le bazar dans un code). Ces classes abstraites ne doivent donc pas servir à dire ce qu’une classe sait faire ou pour le typehinting (c’est le rôle d’une
interface
), mais simplement pour éviter de répéter certaines logiques entre différentes classes. Attention tout de même à ne pas confondre cela avec la composition ($objet = new ObjectDecorator(new Object(...));) qui permet surtout d’imbriquer des logiques.

Débordement d’entier

PHP n’a pas de notion unsigned, contrairement à MySQL. Cela signifie que si MySQL contient un BIGINT UNSIGNED, alors PHP l’interprètera comme un flottant, menant à des erreurs d’arrondis possible. Donc, évitez de faire transiter des BIGINT|INT UNSIGNED entre PHP et MySQL. Les autres types d’entiers MySQL ne présenteront pas de problème, car un TINYINT|SMALLINT|MEDIUMINT UNSIGNED ne dépasse pas la taille maximale d’un INT (2^32-1) et ils ne seront donc pas convertis en double|float par PHP.

DOMDocument

N’utilisez surtout pas d’expression régulière pour valider/manipuler du HTML ou du XML! Utilisez plutôt DOMDocument, une classe native de PHP vous permettra de manipuler ces contenus HTML/XML, de récupérer des informations qu’ils contiennent via XPath et de leur appliquer un template grâce à XSLTProcessor.

Exceptions natives

Les exceptions natives de PHP sont très pratiques à utiliser car elles vous permettent de lever la plupart des exceptions courantes, sans devoir implémenter une classe spécifique à votre projet. Toutefois, essayez de ne pas trop en abuser et n’hésitez pas à créer des classes dédiées à certains types d’exception, qui étendent ces exceptions de base (comme class InvalidInputException extends UnexpectedValueExceptionimplements IInputException). Les exceptions PHP natives sont réparties en deux groupes: les exceptions de logique, qui nécessitent un fix de votre code (LogicException BadFunctionCallException BadMethodCallException DomainException InvalidArgumentException LengthException OutOfRangeException) et les exception d’exécution, qui n’en nécessitent pas mais représente une exécution anormale (RuntimeException OutOfBoundsException OverflowException RangeException UnderflowException UnexpectedValueException). La doc vous en détaillera l’usage.

filter_input

filter_input est la fonction à utiliser pour récupérer les entrées utilisateur. Bannissez

$_POST $_GET $_REQUEST $_COOKIE
car ces variables n’ont pas été validées et peuvent contenir n’importe quoi (voire, ne pas exister). A l’inverse,
filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT)
vous permettra de récupérer la donnée d’entrée de l’utilisateur, et de valider son typage. Voyez la documentation de PHP pour plus de détails.

Heredoc (syntaxe)

La syntaxe Heredoc vous permet de créer des blocs de texte (string) en PHP contenant des retours à la ligne, sans devoir procéder à l’échappement des caractères " ou '. Utilisez-la quand vous avez des chaines de caractères de plusieurs lignes comme une requête SQL.

<<<SQL
SELECT *
FROM mytable AS t
INNER JOIN myothertable AS o ON o.id = t.id_other
WHERE t.id = ?
SQL;

json_encode

Utilisez-le pour échapper toute donnée à insérer dans un javascript ou dans une balise script (

&lt;script&gt;var DATA = &lt;?php echo json_encode($myVar); ?&gt;;...
). Attention à sa complexité non-linéaire: encoder un énorme tableau sera bien plus long qu’encoder des morceaux de ce tableau (voir la discussion sur JeuWeb et l’exemple correspondant).

NULL et NaN

null == null en PHP car il représente un élément (une variable) “vide” (non initialisée). C’est différent de MySQL, pour qui (NULL === NULL)? renvoie… UNKNOWN ! NaN !== NaN en PHP car il représente un nombre qui n’est pas réel (soit un nombre complexe, soit un nombre impossible à évaluer).

switch ou class?

Un switch est très pratique pour gérer une énumération (

switch ($unit->type) { case 'CIVIL': ... case 'MILITARY': ... case 'RESEARCH': ... }
) mais privilégiez des class dans certains cas (
class Civil { ... } class Military { ... } class Research { ... }
) car cela vous évitera des lourdeurs et des redites. N’utilisez le switch qu’une seule fois: un code qui fait passer une variable dans plusieurs switch est certainement à refactorer.

Transtypage

Quand PHP effectue une comparaison de variables, il effectue un transtypage automatique. Cela signifie que

'01' == 1
vaut true. Pour que PHP compare deux variables sans transtypage, utilisez
'01' === 1
qui renvoie alors false. La différence peut être capitale quand vous récupérez des données de la BDD pour les comparer aux entrées utilisateur:
$anIntFromTheUserInput == $aMd5FromTheDatabase
pourrait renvoyer true, par exemple si
37 == md5('bar')
. Egalement, castez vos variables au plus tôt, et favorisez les
$id = (int)filter_input(INPUT_POST, 'userid', FILTER_VALIDATE_INT);
.

WHERE IN (?,...?) et performances

PHP, et surtout PDO, sont très mauvais pour faire des requêtes préparées avec énormément de paramètres. En pratique, la durée de préparation de la requête est presque proportionnelle au carré du nombre de paramètres. Si vous doublez le nombre de ?, alors vous quadruplez la durée de la requête (et cela ne vient pas de MySQL, mais bien de PHP)! Donc, limitez-vous à quelques paramètres: si vous atteignez la centaine, voire le millier, vous commencerez à voir une différence (télécharger la démo PHP). Dans ce genre de cas, il vous vaudra souvent mieux faire une sous-requête, dont le contenu de votre WHERE IN est généralement issu. En d’autres mots, remplacer vos

$ids = $pdo->query('SELECT id FROM...'); $data = $pdo->query('SELECT ... WHERE ... IN (?,...?)');
par un
SELECT ... WHERE ... IN (SELECT id FROM ...)
.

Liens utiles