自动添加到关键字字符串的链接

时间:2018-10-23 07:42:23

标签: php arrays algorithm

在我的文章中,我想自动向关键字添加链接。 我的关键字数组:

 $keywords = [
       0=>['id'=>1,'slug'=>'getName','url'=>'https://example.com/1'],
       1=>['id'=>2,'slug'=>'testName','url'=>'https://example.com/2'],
       2=>['id'=>3,'slug'=>'ign','url'=>'https://example.com/3'],
    ];

这是我的代码:

private function keywords_replace(string $string, array $key_array)
{
    $array_first = $key_array;
    $array_last = [];
    foreach ($array_first as $key=>$value)
    {
        $array_last[$key] = [$key, $value['slug'], '<a target="_blank" href="' . $value['url'] . '" title="' . $value['slug'] . '">' . $value['slug'] . '</a>'];
    }
    $count = count($array_last);
    for ($i=0; $i<$count;$i++)
    {
        for ($j=$count-1;$j>$i;$j--)
        {
            if (strlen($array_last[$j][1]) > strlen($array_last[$j-1][1]))
            {
                $tmp = $array_last[$j];
                $array_last[$j] = $array_last[$j-1];
                $array_last[$j-1] = $tmp;
            }
        }
    }
    $keys = $array_last;
    foreach ($keys as $key)
    {
        $string = str_ireplace($key[1],$key[0],$string);
    }
    foreach ($keys as $key)
    {
        $string = str_ireplace($key[0],$key[2],$string);
    }
    return $string;
}

结果:

 $str = "<p>Just a test: getName  testName";
 echo $this->keywords_replace($str,$keywords);

像这样:只需测试:getName testName
非常导入:如果字符串中没有空格,则不会匹配。由于我将使用其他语言,因此句子中将不会包含英语等空格。像Wordpress关键字自动链接一样

我认为我的代码并不完美,是否有更好的算法来实现此功能?谢谢!

4 个答案:

答案 0 :(得分:1)

首先,您需要使用将结果存储在$newKeywords中的循环将数组的结构更改为键/值。然后使用preg_replace_callback()选择字符串中的每个单词,并检查它是否存在于数组键中。如果存在,请将其包装在锚定标记中。

$newKeywords = [];
foreach ($keywords as $keyword)
    $newKeywords[$keyword['slug']] = $keyword['url'];

$newStr = preg_replace_callback("/(\w+)/", function($m) use($newKeywords){
    return isset($newKeywords[$m[0]]) ? "<a href='{$newKeywords[$m[0]]}'>{$m[0]}</a>" : $m[0];
}, $str);

输出:

<p>Just a test: <a href='https://www.getname.com'>getName</a>  <a href='https://www.testname.com'>testName</a></p>

demo中查看结果

答案 1 :(得分:1)

您可以使用array_reducepreg_replace用相应的slug值替换字符串中所有出现的url字:

$keywords = [
       0=>['id'=>1,'slug'=>'getName','url'=>'https://www.getname.com'],
       1=>['id'=>2,'slug'=>'testName','url'=>'https://www.testname.com'],
       2=>['id'=>3,'slug'=>'ign','url'=>'https://www.ign.com'],
    ];
$str = "<p>Just a test: getName  testName";
echo array_reduce($keywords, function ($c, $v) { return preg_replace('/\\b(' . $v['slug'] . ')\\b/', $v['url'], $c); }, $str);

输出:

<p>Just a test: https://www.getname.com https://www.testname.com

Demo on 3v4l.org

更新

要将文本更改为链接,您需要使用以下代码:

echo array_reduce($keywords, 
                  function ($c, $v) { 
                     return preg_replace('/\\b(' . $v['slug'] . ')\\b/',
                                         '<a href="'. $v['url'] . '">$1</a>', $c);
                  }, 
                  $str);

输出:

<p>Just a test: <a href="https://www.getname.com">getName</a> <a href="https://www.testname.com">testName</a>

Updated demo

更新2

由于某些被替换的链接包含的单词也是slug的值,因此有必要使用strtr的数组格式立即进行所有替换。我们使用array_columnarray_combinearray_map构建一系列模式和替换,然后将其传递给strtr

$reps = array_combine(array_column($keywords, 'slug'),
                      array_map(function ($k) { return '<a href="' . $k['url'] .'">' . $k['slug'] . '</a>'; }, $keywords
                      ));
$newstr = strtr($str, $reps);

New demo

答案 2 :(得分:1)

我的答案与上述Nick's一样使用preg_replace。

它依赖于模式和替换大小相等的数组,以及相应的模式和替换。

需要尊重单词边界,我怀疑您可以通过简单的字符串替换来做到这一点。

<?php
$keywords = [
    0=>['id'=>1,'slug'=>'foo','url'=>'https://www.example.com/foo'],
    1=>['id'=>2,'slug'=>'bar','url'=>'https://www.example.com/bar'],
    2=>['id'=>3,'slug'=>'baz','url'=>'https://www.example.com/baz'],
];

foreach ($keywords as $item)
{
    $patterns[]     = '@\b(' . $item['slug'] . ')\b@i';
    $replacements[] = '<a href="' . $item['url'] . '">$1</a>';
}

$html = "<p>I once knew a barbed man named <i>Foo</i>, he often visited the bar.</p>";

print preg_replace($patterns, $replacements, $html);

输出:

<p>I once knew a barbed man named <i><a href="https://www.example.com/foo">Foo</a></i>, he often visited the <a href="https://www.example.com/bar">bar</a>.</p>

答案 3 :(得分:0)

这是我的答案:感谢@Nick

$content = array_reduce($keywords , function ($c, $v) {
    return preg_replace('/(>[^<>]*?)(' . $v['slug'] . ')([^<>]*?<)/', '$1<a href="'. $v['url'] . '">$2</a>$3', $c);
}, $str);