Заменить текст гиперссылками там, где его еще нет - PullRequest
6 голосов
/ 25 января 2012

Лучшим примером будет следующий:

$string = "That is a very nice ford mustang, if only every other ford was quite as nice as this honda";

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

$remove = array("ford mustang","ford","honda");
$replaceWith = array("<a href='fordID'>ford</a>","<a href='fordmustangID'>ford mustang</a>","<a href='hondaID'>honda</a>");

Это дает результат:

"That is a very nice <a href='<a href='fordmustangID'>ford mustang</a>ID'><a href='fordmustangID'>ford mustang</a></a>, if only every other <a href='fordmustangID'>ford mustang</a> was quite as nice as this <a href='hondaID'>honda</a>"

Я хочу создать гиперссылку, только если нет 'т один уже так:

  "That is a very nice <a href='fordmustangID'>ford mustang</a>, if only every other <a href='fordID'>ford</a> was quite as nice as this <a href='hondaID'>honda</a>"

1 Ответ

4 голосов
/ 25 января 2012

редактирование:

Мне понадобилось немного времени, но вот что я придумал:

function replaceLinks($replacements, $string){
    foreach($replacements as $key=>$val){
        $key=strtolower((string)$key);
        $newReplacements[$key]=array();
        $newReplacements[$key]['id']=$val;
        //strings to make sure the search isn't in front of
        $newReplacements[$key]['behinds']=array();
        //strings to make sure the search isn't behind
        $newReplacements[$key]['aheads']=array();
        //check for other searches this is a substring of
        foreach($replacements as $key2=>$val2){
            $key2=(string)$key2;
            /* 
            //debugging
            $b = ($key=='11 22'&&$key2=='11 22 33');
            if($b){
                l('strlen $key2: '.strlen($key2));
                l('strlen $key: '.strlen($key));
                l('strpos: '.(strpos($key2,$key)));

            }
            */
            //the second search is longer and the first is a substring of it
            if(strlen($key2)>strlen($key) && ($pos=strpos($key2,$key))!==false){
                //the first search isn't at the start of the second search ('the ford' and 'ford')
                if($pos!=0){
                    $newReplacements[$key]['behinds'][]=substr($key2,0,$pos);
                }
                //it's not at the end ('ford' and 'fords')
                if(($end=$pos+strlen($key))!=strlen($key2)){
                    $newReplacements[$key]['aheads'][]=substr($key2,$end);
                }
            }
        }
    }
    foreach($newReplacements as $key=>$item){
        //negative lookbehind for words or >
        $tmp="/(?<![\w>=])";
        //negative lookbehinds for the beginnings of other searches that this search is a subtring of
        foreach($item['behinds'] as $b){
            $tmp.="(?<!$b)";
        }
        //the actual search
        $tmp.="($key)";
        //negative lookaheads for ends of other searches that this is a substring of.
        foreach($item['aheads'] as $a){
            $tmp.="(?!$a)";
        }
        //case insensitive
        $tmp.='/ie';
        $replacementMatches[]=$tmp;
    }
    return preg_replace($replacementMatches,'"<a href=\"".$newReplacements[strtolower("$1")]["id"]."\">$1</a>"' ,$string);

}

Передайте ему массив, такой как тот, о котором вы говорили:

$replaceWith = array('ford mustang'=>123,'ford'=>42,'honda'=>324);

и строка:

$string = "That is a very nice ford mustang, if only every other ford was quite as nice as this honda";

echo replaceLinks($replaceWith,$string);

Он дает приоритет большим строковым ключам, поэтому, если у вас есть ford и ford mustang, он заменит ford mustang ссылкой.




Не очень практично, но может сработать.

$string = "That is a very nice ford mustang, if only every other ford was quite as nice as this honda";
$remove = array("/(?<![\w>])ford mustang(?![\w<])/",'/(?<![>\w])ford(?! mustang)(?![<\w])/',"/(?<![>\w])honda(?![<\w])/");
$replaceWith = array("<a href='fordmustangID'>ford mustang</a>","<a href='fordID'>ford</a>","<a href='hondaID'>honda</a>");
echo preg_replace($remove, $replaceWith,$string);

Я использовал регулярные выражения с отрицательными символами «lookaheads» и «lookbehind», чтобы убедиться, что часть строки, которую мы заменяем, не является частью буквенно-цифровой последовательности (например, 12ford23 или afford) или касалась начального или конечного тега элемент.

...