Замена слов ссылками на теги в PHP - PullRequest
6 голосов
/ 18 августа 2010

У меня есть текст ($text) и массив слов ($tags).Эти слова в тексте должны быть заменены ссылками на другие страницы, чтобы они не нарушали существующие ссылки в тексте.В CakePHP есть метод в TextHelper для этого, но он поврежден и нарушает существующие HTML-ссылки в тексте.Предполагается, что метод работает следующим образом:

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

Ниже приведен код в 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);
  }
}

Ответы [ 4 ]

2 голосов
/ 13 октября 2010

Вы можете увидеть (и запустить) этот алгоритм здесь:

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

Его можно сделать немного лучше и проще с несколькими изменениями, но все же он не идеален. Хотя это и менее эффективно, я бы порекомендовал одно из решений Ben Doom.

1 голос
/ 08 октября 2010

Замена текста в HTML принципиально отличается от замены обычного текста. Чтобы определить, является ли текст частью HTML-тега, необходимо найти все теги, чтобы не учитывать их. Regex на самом деле не инструмент для этого.

Я бы попробовал одно из следующих решений:

  • Найдите позиции всех слов. Работая от последнего к первому, определите, является ли каждый из них частью тега. Если нет, добавьте якорь.
  • Разделить строку на блоки. Каждый блок представляет собой тег или простой текст. Запустите замену (-и) для блоков простого текста и соберите заново.

Я думаю, что первый, возможно, немного более эффективен, но более подвержен ошибкам программиста, поэтому я оставлю это на ваше усмотрение.

Если вы хотите знать, почему я не подхожу к этой проблеме напрямую, посмотрите все вопросы на сайте о регулярных выражениях и HTML и о том, как регулярное выражение не является синтаксическим анализатором.

0 голосов
/ 30 августа 2010

Аморфность - я заметил, что Герт отредактировал ваше сообщение.Являются ли два фрагмента кода точно в том виде, в каком вы их опубликовали?

Итак, хотя оригинальный код был разработан для выделения, я понимаю, что вы пытаетесь использовать его для генерации ссылок - он должени отлично работает для этого (проверено как опубликовано).

ОДНАКО экранирование в первом фрагменте кода может быть проблемой.

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

Работает нормально ...но если вы используете речевые метки, а не кавычки, обратные слеши исчезают как escape-метки - вам нужно их избегать.Если нет, вы получаете% 01 ссылки.

Правильный путь с метками речи:

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

(обратите внимание на использование \ 1 вместо \ 1)

0 голосов
/ 18 августа 2010

Этот код работает просто отлично. Что вам может понадобиться, это проверить CSS для <span class="highlight"> и убедиться, что для него задан какой-то цвет, который позволит вам различить, что он ярко освещен.

.highlight { background-color: #FFE900; }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...