Ah oui les variables dynamiques, on est toujours fier de les placer. Et puis on s’absente quinze jours, et au retour on percute plus rien à ce qu’on a codé
La clarté du code est plus importante qu’un éphémère sentiment de fierté. Moi par exemple, tu as réussi à m’embrouiller : il a fallu que je m’accroche pour comprendre quels noms de variables réels étaient utilisés in fine dans le script, et aussi réaliser que tu n’avais pas tout à fait compris comment on utilise preg_replace. Confer la doc :
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
mixed est un mot-clé de la doc qui signifie « un mélange de plusieurs types ». Il faut lire ce qui est en-dessous pour connaître les détails. En l’occurence, $pattern et $replacement peuvent être des tableaux, auquel cas la fonction détecte que ce sont des tableaux et les parcourt automatiquement, tu n’as donc pas besoin de faire une boucle.
Exemple :
echo preg_replace([ '/a/', '/b/' ], [ 'X', 'Y' ], 'abcabcabc');
D’autre part, j’ai un début d’explication sur pourquoi ça marche les deux premières fois mais pas après. À partir du 3e traitement, tes tableaux ont plusieurs dimensions :
1 2 3 4 5
| 0 =>
array (size=1)
0 =>
array (size=1)
0 => string 'Array' (length=5) |
On voit des chaînes 'Array' qui sont le résultat d’une conversion de tableau en chaîne. Ce sont ces conversions qui génèrent les messages notice que tu as vus.
Je pense que le coupable est ce array que tu mets autour de ton preg_replace à la ligne 62.
Pour résumer, laisse preg_match s’occuper des tableaux de patterns et de remplacements, elle fait ça très bien toute seule.
La doc nous dit aussi que $subject peut être un tableau. Puisque tes chaînes à traiter sont déjà dans un tableau, preg_match peut itérer dessus également. Au final, tu n’as aucune boucle à écrire !
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| ...
// découpage du fichier dans un array
$lines0 = file($path);
// Tableau qui contient les différents patterns de mes regEx
$aPattern = array(
'/(include|require){1}(_once)?[ ]?[\(]?[\'"](.*?)[\'"][\)]?[ ]?;/im',
'/(_once){1}/im',
'/(include){1}/im',
'/(require){1}/im'
);
// Tableau qui contient les replace qui correspondent aux patterns
$aReplace = array(
'${1}${2} ROOT . \'${3}'.'\';',
'_once',
'include',
'require'
);
var_dump(
preg_replace($aPattern, $aReplace, $lines0)
); |
Au fait, quelques suggestions à propos de tes patterns.
- Tu peux virer les {1}, ils ne servent à rien. Une correspondance est reconnue une seule fois de base.
- Les [ ]? sont des classes à un seul caractère, l’espace. Tu peux les remplacer par ?, ou \s? pour plus de clarté. Note que PHP autorise plusieurs espaces à la suite, donc \s* à la place de \s? rendrait ton pattern plus robuste.
- De la même façon, tu peux retirer les crochets autour de \( et \).
- Le drapeau /m ne change rien quand tu n’utilises pas les ancres ^ et $ ; de plus, ton fichier est déjà découpé en lignes par la fonction file.
- Tu peux utiliser une référence arrière pour faire correspondre le type de guillemet : '/([\'"])(.*?)\1/'. Pour ça, attention aux groupes capturants. Chaque paire de parenthèses constitue un groupe capturant, et les références sont comptées en prenant la parenthèse ouvrante. Si tu ne veux pas qu’un groupe soit capturant, il faut écrire (?: ... ).
- Pour finir, tes trois derniers patterns ne font rien que le premier ne fait déjà, donc tu peux les supprimer.
Au final, voici à quoi ta regex pourrait ressembler :
1 2
| '/((?:include|require)(?:_once)?)\s*\(?([\'"])(.*?)\2\)?\s*;/i',
( 1 ) ( 2 )( 3 ) |
J’ai indiqué les groupes capturants en-dessous avec leurs numéros de référence. Cette regex te renverra par exemple INCLUDE_ONCE en groupe 1, que tu pourras traiter avec strtolower ou mb_strtolower ; le guillemet en groupe 2 ; et le chemin du fichier en groupe 3.
Partager