2010-08-18 20 views
6

Ho un testo ($text) e una serie di parole ($tags). Queste parole nel testo dovrebbero essere sostituite con collegamenti ad altre pagine in modo che non interrompano i collegamenti esistenti nel testo. In CakePHP c'è un metodo in TextHelper per farlo, ma è corrotto e rompe i collegamenti HTML esistenti nel testo. Il metodo si supponga di lavorare in questo modo:Sostituzione di parole con collegamenti di tag in PHP

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

Qui di seguito c'è il codice esistente in 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); 
    } 
} 

risposta

0

Questo codice funziona bene. Quello che potrebbe essere necessario fare è controllare il CSS per il <span class="highlight"> e assicurarsi che sia impostato su un colore che ti permetterà di distinguere che è illuminato in alto.

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

Non sto chiedendo di evidenziare. Si prega di leggere la domanda. – Amorphous

+0

Fornirai un esempio di '$ text' da esaminare? Il codice funziona bene quando lo provo. Direi che potrebbe essere che i '$ tag' che stai cercando di sostituire possano esistere all'interno di un tag'

0

Amorfo - Ho notato che Gert ha modificato il tuo post. I due frammenti di codice esattamente come li hai pubblicati?

Quindi, anche se il codice originale è stato progettato per l'evidenziazione, capisco che stai cercando di riutilizzarlo per generare link - dovrebbe, e funziona bene per quello (testato come pubblicato).

TUTTAVIA l'escaping nel primo frammento di codice potrebbe essere un problema.

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

funziona bene ... ma se si utilizza speach marchi piuttosto che citare segna le barre inverse scompaiono come segni di fuga - è necessario sfuggire loro. Se non ottieni i link% 01.

Il modo corretto con i segni speach è:

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

(notare l'uso di \ 1 al posto di \ 1)

1

Sostituzione testo in HTML è fondamentalmente diverso da quello di sostituire testo normale. Per determinare se il testo fa parte di un tag HTML è necessario trovare tutti i tag per non considerarli. Regex non è davvero lo strumento per questo.

vorrei tentare una delle seguenti soluzioni:

  • Trova le posizioni di tutte le parole. Lavorando dall'ultimo al primo, determina se ognuno fa parte di un tag. In caso contrario, aggiungi l'ancora.
  • Dividere la stringa in blocchi. Ogni blocco è un tag o un testo semplice. Esegui le tue sostituzioni sui blocchi di testo normale e riassembla.

Penso che il primo sia probabilmente un po 'più efficiente, ma più incline agli errori del programmatore, quindi lascerò tutto a voi.

Se vuoi sapere perché non sto affrontando direttamente questo problema, guarda tutte le domande sul sito riguardo regex e HTML, e su come regex non è un parser.

2

Si può vedere (ed eseguire) questo algoritmo qui:

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

Può essere fatto un po 'meglio e più semplice con alcune modifiche, ma non è ancora perfetto. Anche se meno efficiente, consiglierei una delle soluzioni di Ben Doom.

Problemi correlati