PHP:查找子字符串,使用动态属性包装标记

时间:2016-04-28 18:56:34

标签: php html arrays regex

我正在为网站制作词汇表自动工具提示功能。这将允许管理员输入带有相应定义的术语表术语,然后这些单词将在它们出现在前端的任何地方被制作成可移动的工具提示触发器。

以下是我使用的方法:

所有内容在通过函数输出之前进行过滤,该函数使用正则表达式搜索词汇表术语,并将它们包含在带有类的标记中,然后由javascript选取该类以处理工具提示的悬停显示。

我需要它做什么,并且无法弄清楚,还要包括适当的定义作为跨度的标题属性。

到目前为止,这是我的代码: (初始数组只是示例,每个数据中都有更多条目)

function glossary_highlight( $content ) {
    $glossary = ['Lorem', 'Ipsum'];
    $definitions = ['Lorem is a type of crocodile', 'Ipsum is a kitchen utensil'];
    $patterns = [];
    foreach ($glossary as $term) {
        $patterns[] = '/\b' . $term . '\b/i';
    }
    $wrapper = '<span class="tooltip" title="XXXX">$0</span>';
    $wrapped = preg_replace($patterns, $wrapper, $content);
    return $wrapped;
}

我需要用$ definitions数组中的相应条目替换XXXX。我无法在foreach循环中执行正则表达式,因为如果定义包含另一个词汇表术语等,它可能会开始在其他跨度的标题中添加跨度。

期望的效果 - 给予一个$含量的Lorem ipsum dolor sit amet&#34;,这个函数的回报应该是:

<span class="tooltip" title="Lorem is a type of crocodile">Lorem</span> <span class="tooltip" title="Ipsum is a kitchen utensil">ipsum</span> dolor sit amet

我的第一个倾向是做类似的事情:

$wrapper = '<span class="tooltip" title="' . $definitions[$key] . '">$0</span>';

其中$ key将与相关词汇表术语的索引相关,但我无法弄清楚如何将其用于foreach。

如果我无法在PHP中解决这个问题,我想我会应用工具提示范围并将定义数组发送到javascript以从那里附加title属性,但我不想拆分两种语言的基本任务......

我确定这里有一个非常简单的答案,但我的大脑不会看到它!有人可以帮忙吗?

编辑:感谢萤火虫对他的帮助,代码如下:

function glossary_highlight( $content ) {
    $glossary = ['Lorem', 'Ipsum'];
    $definitions = ['Lorem is a type of crocodile', 'Ipsum is a kitchen utensil'];
    $patterns = [];
    foreach ($glossary as $term) {
        $patterns[] = '/\b' . $term . '\b/i';
    }
    $wrappers = [];
    foreach ($definitions as $definition) {
        $wrappers[] = '<span class="tooltip" title="' . $definition . '">$0</span>';
    }
    $wrapped = preg_replace($patterns, $wrappers, $content);
    return $wrapped;
}

2 个答案:

答案 0 :(得分:0)

我看到两个选项:

  1. 为每个学期运行一次preg_replace。如果文本很长,那么术语很多并且这是实时完成的,这可能会成为性能问题。
  2. 提供一系列替换,就像您对模式一样。
  3. 我认为2号通常会更快而且更简单。我的想法是建立这样的包装器:

    $wrappers = [];
    foreach ($definitions as $definition) {
        $wrappers[] = '<span class="tooltip" title="' . $definition . '">$0</span>';
    }
    

    ...然后使用包装器:

    $wrapped = preg_replace($patterns, $wrappers, $content);
    

答案 1 :(得分:0)

我会将你的标记存储在一个关联数组中。它更干净,更容易看到匹配。

$words = [
    'lorem' => 'Lorem is a type of crocodile',
    'ipsum' => 'Ipsum is a kitchen utensil',
];

然后构建模式。注意在这里使用\ b字边界锚,以便我们匹配lorem但不匹配splorems。

$patterns = [];
foreach (array_keys($words) as $word) {
    $patterns[] = '/\b' . $word . '\b/i';
}

然后使用preg_replace_callback()动态生成自定义替换字符串:

$newContent = preg_replace_callback($patterns, function ($matches) use ($words) {
    return
        '<span class="tooltip" title="' .
        $words[strtolower($matches[0])] .
        '">' . $matches[0] . '</span>';
}, $content);