2012-03-07 17 views
5

tengo algo de código como este, que sustituye algunos códigos cortos con un enlace:¿Hay un preg_replace condicional en 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); 

tengo mucho más que son similares así que me preguntaba, ¿hay alguna manera de reducir esto a una sencilla preg_replace con un condicional ?

Por ejemplo, use la expresión regular #\{([a-z])\|([^|]+)\|([^}]+)\}# y reemplace la primera coincidencia con algo diferente (r = ref, t = tipo) según su letra? (Si ayuda, los códigos cortos son como {r|url-slug|LinkTitle}.)

Respuesta

9

Esto exige preg_replace_callback (o, posiblemente, sólo la /e modificador eval), lo que permitirá poner el mapeo t = type y r = ref en la lógica de sustitución:

= 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

RENUNCIA: lo que sigue a continuación es un mal consejo, y sugiere el uso de una característica de PHP que está con razón obsoleto. Solo lo dejo aquí para una referencia histórica.

Utilice la técnica sugerida en la respuesta aceptada.


La alternativa a la (perfectamente válido) preg_replace_callback() método sugerido por @mario es el modificador e, que sólo está disponible con preg_replace() y permite que su cadena para ser evaluado como código 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); 

El único problema que se me ocurre es que si su LinkTitle contiene una comilla simple, se escapará y aparecerá como \' en la salida.

See it working

EDITAR

Después de un poco de ensayo y error, aquí es una versión que funciona con cualquier cosa que puede lanzar en él, y también pasa todos los datos a través de urlencode()/htmlspecialchars() en su 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); 

Salidas:

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