2012-03-07 5 views
5

ho qualche codice come questo, che sostituisce alcuni codici brevi con un link:Esiste un preg_replace condizionale in PHP?

$search = array(
    '#\{r\|([^|]+)\|([^}]+)\}#', 
    '#\{t\|([^|]+)\|([^}]+)\}#', 
    ..., 
); 

$replace = array(
    '<a href="/ref/$1">$2</a>', 
    '<a href="/type/$1">$2</a>', 
    ..., 
); 

$content = preg_replace($search, $replace, $content); 

Ho un sacco di più che sono simili quindi mi chiedevo, c'è qualche modo per ridurre questo ad una semplice preg_replace con un condizionale ?

Ad esempio, utilizzare la regex #\{([a-z])\|([^|]+)\|([^}]+)\}# e sostituire la prima corrispondenza con qualcosa di diverso (r = ref, t = tipo) in base alla sua lettera? (Se aiuta, i codici brevi sono come {r|url-slug|LinkTitle}.)

risposta

9

Ciò richiede preg_replace_callback (o forse solo il modificatore eval /e), che permetterà di mettere la mappatura t = type e r = ref nella logica di sostituzione:

= preg_replace_callback('#\{([rt])\|([^|]+)\|([^}]+)\}#', "cb_123", ... 

function cb_123($m) { 

    $map = array("t" => "type", "r" => "ref"); 
    $what = $map[ $m[1] ]; 

    return "<a href=\"/$what/$m[2]\">$m[3]</a>"; 
} 
3

NOTA BENE: quello che segue sotto è consiglio terribile, e suggerisce l'uso di una funzione di PHP che è giustamente ora sconsigliato. Lo lascio qui solo per un riferimento storico.

Utilizzare la tecnica suggerita nella risposta accettata.


L'alternativa alla (perfettamente valido) preg_replace_callback() metodo suggerito dal @mario è il modificatore di e, che è disponibile solo con preg_replace() e permette la vostra stringa di sostituzione per essere valutata come codice PHP:

<?php 

    $shortCodes = array (
    'r' => 'ref', 
    't' => 'type' 
    ); 

    $expr = '#\{([a-z])\|([^|]+)\|([^}]+)\}#e'; 
    $replace = '"<a href=\"/{$shortCodes[\'$1\']}/$2\">$3</a>"'; 
    $string = 'Some text as a ref {r|link1.php|link} and a type {r|link2.php|link}'; 

    echo preg_replace($expr, $replace, $string); 

L'unico problema che posso pensare è se il tuo LinkTitle contiene una virgoletta singola che sarà sfuggito e che appare come \' nell'output.

See it working

EDIT

Dopo un po 'di tentativi ed errori, qui è una versione che funziona con tutto ciò che si può buttare a questo, e anche passa tutti i dati attraverso urlencode()/htmlspecialchars() se del caso:

<?php 

    $shortCodes = array (
    'r' => 'ref', 
    't' => 'type' 
); 

    $expr = array(
    '#\{([a-z])\|([^|]+)\|([^}]*"[^}]*)\}#e', 
    '#\{([a-z])\|([^|]+)\|([^}]+)\}#e' 
); 
    $replace = array(
    '"<a href=\"/{$shortCodes[\'$1\']}/".htmlspecialchars(urlencode(\'$2\'))."\">".htmlspecialchars(str_replace(\'\"\', \'"\', \'$3\'))."</a>"', 
    '"<a href=\"/{$shortCodes[\'$1\']}/".htmlspecialchars(urlencode(\'$2\'))."\">".htmlspecialchars(\'$3\')."</a>"' 
); 
    $string = 'Some text as a ref {r|link &1.php|link&\' with some bad characters in it} and a type {r|link2.php|link with some "quotes" in it}'; 

    echo preg_replace($expr, $replace, $string); 

Uscite:

Some text as a ref <a href="/ref/link+%261.php">link&amp;' with some bad characters in it</a> and a type <a href="/ref/link2.php">link with some &quot;quotes&quot; in it</a>

See it working