2010-08-18 13 views
6

Tengo un texto ($text) y una matriz de palabras ($tags). Estas palabras en el texto deben reemplazarse por enlaces a otras páginas para que no rompan los enlaces existentes en el texto. En CakePHP hay un método en TextHelper para hacer esto pero está dañado y rompe los enlaces HTML existentes en el texto. El método supone que debe funcionar así:Reemplazar palabras con enlaces de etiqueta en PHP

$text=Text->highlight($text,$tags,'<a href="/tags/\1">\1</a>',1); 

A continuación se presenta el código existente en CakePHP TextHelper:

function highlight($text, $phrase, $highlighter = '<span class="highlight">\1</span>', $considerHtml = false) { 
    if (empty($phrase)) { 
    return $text; 
    } 

    if (is_array($phrase)) { 
    $replace = array(); 
    $with = array(); 

    foreach ($phrase as $key => $value) { 
     $key = $value; 
     $value = $highlighter; 
     $key = '(' . $key . ')'; 
     if ($considerHtml) { 
     $key = '(?![^<]+>)' . $key . '(?![^<]+>)'; 
     } 
     $replace[] = '|' . $key . '|ix'; 
     $with[] = empty($value) ? $highlighter : $value; 
    } 
    return preg_replace($replace, $with, $text); 
    } else { 
    $phrase = '(' . $phrase . ')'; 
    if ($considerHtml) { 
     $phrase = '(?![^<]+>)' . $phrase . '(?![^<]+>)'; 
    } 

    return preg_replace('|'.$phrase.'|i', $highlighter, $text); 
    } 
} 

Respuesta

0

Este código funciona bien. Lo que debe hacer es verificar el CSS para el <span class="highlight"> y asegúrese de que esté configurado con un color que le permita distinguir que está iluminado.

.highlight { background-color: #FFE900; } 
+0

No estoy preguntando sobre resaltar. Por favor lea la pregunta. – Amorphous

+0

¿Ofrecerá la muestra '$ text' para que la vea? El código funciona bien cuando lo pruebo. Diría que es posible que las '$ etiquetas' que desea reemplazar puedan existir dentro de una etiqueta'

0

Amorphous - Me di cuenta que Gert editó su publicación. ¿Los dos fragmentos de código son exactamente cuando los publicó?

De modo que, aunque el código original fue diseñado para resaltar, entiendo que está tratando de reutilizarlo para generar enlaces, debería y funciona bien para eso (probado como se publicó).

SIN EMBARGO escaparse en el primer fragmento de código podría ser un problema.

$text=Text->highlight($text,$tags,'<a href="/tags/\1">\1</a>',1); 

funciona bien ... pero si se utiliza speach marcas en lugar de la cita marca las barras invertidas desaparecen como marcas de escape - que necesita para escapar de ellos. Si no lo haces, obtienes enlaces de% 01.

La forma correcta con marcas speach es:

$text=Text->highlight($text,$tags,"<a href=\"/tags/\\1\">\\1</a>",1); 

(Nótese el uso de \ 1 en lugar de \ 1)

1

Sustitución de texto en HTML es fundamentalmente diferente de la sustitución de texto plano. Para determinar si el texto es parte de una etiqueta HTML, debe buscar todas las etiquetas para no tenerlas en cuenta. Regex no es realmente la herramienta para esto.

intentaría una de las siguientes soluciones:

  • Encuentra las posiciones de todas las palabras. Trabajando de último a primero, determine si cada uno es parte de una etiqueta. Si no, agregue el ancla.
  • Divida la cadena en bloques. Cada bloque es una etiqueta o texto sin formato. Ejecute su (s) reemplazo (s) en los bloques de texto sin formato, y vuelva a armarlo.

Creo que el primero es probablemente un poco más eficiente, pero más propenso a error del programador, así que lo dejo en tus manos.

Si quiere saber por qué no me estoy acercando a este problema directamente, mire todas las preguntas en el sitio sobre regex y HTML, y cómo Regex no es un analizador.

2

Se puede ver (y ejecutar) este algoritmo aquí:

http://www.exorithm.com/algorithm/view/highlight

Se puede hacer un poco mejor y más simple con algunos cambios, pero todavía no es perfecto. Aunque es menos eficiente, recomendaría una de las soluciones de Ben Doom.

Cuestiones relacionadas