Script PHP pour effectuer un search and replace à l’intérieur d’une chaîne de caractères.
Remplacer une chaîne par un lien, une image ou une classe css’
Remplacer une chaîne par une autre est une opération dont on a parfois besoin en cours de développement. Il arrive qu\’on doive remplacer une chaîne par un lien. Dans d’autres circonstances, il peut arriver qu’on ait besoin de remplacer une chaîne par une image. Ou par un balisage HTML destiné à jouer sur le style de l’élément. Voilà une petite fonction qui permet de faire ça assez facilement côté serveur, en PHP.
Pour faire ce genre de chose, il existe des fonctions natives, me direz-vous. De fait. Mais le problème d’une fonction native comme <code>str_replace()</code> ou <code>substr_replace()</code> lorsqu’elle est employée seule, c’est qu’elle ne va pas distinguer les mots entiers des parties de mots, à moins qu’on ne lui renseigne précisément où découper la chaîne. Pour ça, il faut sortir le boulier compteur et bricoler un peu, quoi qu’il advienne.
Expressions régulières alors : PCRE, POSIX … il y a de quoi faire ! Oui, avec une bonne regex, c’est possible. Mais ça consomme. Et écrire une regex, pour certains, ça revient à entamer un sponsoring avec Petrole Hahn.
Du coup, voilà une petite fonction qui permet de faire ça assez facilement. Du coup. Elle est loin d’être parfaite, mais fonctionne parfaitement tout en tenant compte de la ponctuation.
Cela se passe en deux temps : d’abord il faut déterminer si l’expression-clef entière – et non une portion – se trouve bien dans la ressource, en tenant compte de la ponctuation. Ensuite il faut s’occuper de faire le “search&replace”.
/**
* Replace expressions into string per link, image or HTML class attribute
*
* @param int Replace type (1 = link ; 2 = img ; 3 = class)
* @param string Text to scan
* @param array Data (array([0][findMe] -> 'find me', [url] -> 'http://www.my-url.com')
* @param string (optionnal, if type == 3) (div or span)
* @param string (optionnal, if type == 3) (name of the class)
* @return string Text with builded expressions
*/
function searchAndReplace($type , $text , $data , $box = '' , $name = '') {
// Validate inputs
$types = [1, 2, 3];
if (!in_array($type, $types)) {
throw new Error('Unknown type given');
}
// Authorized chars prev/next the expression
$chars[0] = '\';
$chars[1] = '\';
$chars[2] = ',';
$chars[3] = ';';
$chars[4] = '.';
$chars[5] = '!';
$chars[6] = '?';
$chars[7] = '-';
$chars[8] = '/';
$chars[9] = ')';
$chars[10] = '(';
$chars[11] = '\\\';
foreach($data as $key => $value) {
$key == 0 ? $ressource = $text : $ressource = $texter;
// Replace expressions
if($type == 1) {
$replace = '<a href="\' . $value['url'] . '\" target="_blank">' . $value['findMe'] . '</a>';
} else if ($type == 2) {
$replace = '<img src="\' . $value['url'] . '\" />';
} else {
$replace = '<' . $box . \' class="\' . $name . \'">\' . $value['findMe'] . \'>/\' . $box . \'>\';
}
$length = strlen($value['findMe']);
// If expression is not found
if (strpos(strtolower($ressource), strtolower($value['findMe'])) === FALSE) {
return FALSE;
}
// Start position of the occurence
$pos = strpos(strtolower($ressource), strtolower($value['findMe']));
// Char previous the expression
$prev_char = substr($ressource, $pos-1, 1);
// End position of the occurence
$nxtPos = $pos + $length;
// Char next the expression
$next_char = substr($ressource, $nxtPos, 1);
// The expression is complete, but not a segment
if (in_array($prev_char, $chars) && in_array($next_char, $chars)) {
$occInfos = [
'starter' => $pos,
'end' => $nxtPos
];
}
$texter = substr_replace($ressource, $replace, $occInfos['starter'], $length);
}
return $texter;
}
Voilà voilà, il y a moyen de pousser le vice un peu plus loin en ajoutant les paramètres “type”, “box” et “name” non pas dans la fonction, mais dans le tableau “data”, cela permettrait de faire des remplacements hybrides. Il est également possible, par exemple, d’ajouter un évènement au clic sur le div ou le span inséré, ça permettrait de ne pas jeter l’URL à la poubelle.
En vous remerciant, bonsoir.