# 帝国cms如何使用PHP代码实现文章内容关键词加链接

*Published:* 2024-06-03
*Author:* 客服001

#### 温馨提醒

如果文章内容或图片资源失效，请留言反馈，我们会及时处理，谢谢

本文最后更新于2024年6月3日，已超过 180天没有更新



实现文章内关键词自动加链接(用于内链SEO等)，长词优先替换，替换过的不会二次替换，可设置替换数量(一个关键词允许出现N次)等。

找到HotWords.class.php，完整代码如下：

```
<?php

/**
* @abstract 内容热词（<a >热词</a>除外）加超链功能类
* @param string $content 内容
* @param array $keyWords 二维数组，格式： array(
*                                          array('热词1', 'URL1'),
*                                          array('热词2', 'URL2'),
*                                          ...
*                                          array('热词n', 'URLn')
*                                      );
* @param int $times 同一个热词在内容中前$times次都将被加上超链
* @author WKD
*
*/

class HotWords{
    protected $_content;
    protected $_keyWords;
    protected $_times;
   
    public function __construct($content, $keyWords, $times){
        $this->setContent($content);
        $this->setKeyWords($keyWords);
        $this->setTimes($times);
    }
   
    /**
     * @abstract 给热词加链接
     * @access public
     */
    public function addHotLink(){
        /**
         *  思路说明：
         *      1、对关键词数组进行排序，长的关键词排到前面，这样就可以先替换长的关键词
         *      2、提取出所有html标签，暂存到数组里（<a>****</a>整体提取）
         *      3、根据html标签对内容进行分割，将分割的内容保存到一个数组里
         *      4、将没有了html标签的内容数组，用一个“特殊字符（临时替换html标签的中间变量$tempReplaeHtmlTag）”拼接成一个字符串
         *      5、先用加密的热词替换4中得到的字符串中的热词，再用热词本身替换加密的热词
         *      6、根据“特殊字符（临时替换html标签的中间变量）”将5中得到的字符串换成数组
         *      7、拼接6中得到的数组与2中得到的html标签数组，即可。
         */
        
        $content = $this->getContent();                             //得到文章内容
        $kWordsArr = $this->keyWordSort($this->getKeyWords());      //对热词进行排序
        $htmlTagArr = $this->getAllHtmlTag($content);               //得到内容中的html标签
        $noHtmlContentArr = $this->splitContentByTag($content);     //根据html标签对内容进行分割
        $tempReplaeHtmlTag = '{' . md5('lvdora-news') .'}';         //临时替换html标签的中间变量
        
        $tempReplaceArr = array();
        $tempReplaceArr[1] = array();
        $tempReplaceArr[2] = array();
        $tmepReplaceArr[3] = array();   
        $temContent = implode($tempReplaeHtmlTag, $noHtmlContentArr);
        
        //热词与链接对应
        foreach ($kWordsArr as $key => $kWords){
            $tempReplaceArr[1][] = '/' . preg_quote($kWords[0]) . '/i';
            if(strpos($kWords[1], 'http://') === FALSE){
                $tempReplaceArr[2][] = '<a href="http://www.phpin.net' . $kWords[1] . '" class="hotwords" target="_blank">' . $kWords[0] . '</a>';
            }else{
                $tempReplaceArr[2][] = '<a href="' . $kWords[1] . '" class="hotwords" target="_blank">' . $kWords[0] . '</a>';
            }
            $tempReplaceArr[3][] = '{' . md5($kWords[0]) . '}';
        }

        //对没有html标签的内容进行关键字替换，为了防止像“AAA”与“AAAB”的冲突，先用md5后的替换，再用原词替换md5后的
        $temContent = preg_replace($tempReplaceArr[1], $tempReplaceArr[3], $temContent, $this->getTimes());
        $temContent = str_replace($tempReplaceArr[3], $tempReplaceArr[2], $temContent);
        $noHtmlContentArr = explode($tempReplaeHtmlTag, $temContent);
        $result = '';
        foreach ($noHtmlContentArr as $key => $val){
            $result .= $val . $htmlTagArr[$key];
        }
        
        return $result;
        
    }
   
    /**
     * @abstract 根据html标签对内容进行分割，将分割的内容返回。
     * @param string $content 要分割的内容
     * @return array
     */
    protected function splitContentByTag($content){
        return preg_split('/<a[^>]*>.*?<\/a>|<\/?[a-zA-Z]+[^>]*>/', $content);
    }
   
    /**
     * @abstract 等到$content中的所有html标签
     * @param string $content 内容
     * @return unknown|multitype:
     */
    protected function getAllHtmlTag($content){
        
        /**
         * 这边的正则就是将<>包着的内容都提取出来，
         * 凡是需要将<>号当成内容显示的，都应当用转义字符&lt;&gt来替换，
         * 对于一切<>包着的内容都可以认为是标签。
         * 事实上浏览器也是这么干的，很多在线的文本编辑器也会自动转义这些字符。
         */
        preg_match_all('/<a[^>]*>.*?<\/a>|<\/?[a-zA-Z]+[^>]*>/', $content, $match);
        if (isset($match[0])) {
            $htmlTagArray = $match[0];
            return $htmlTagArray;
        }
        return array();
    }
   
    /**
     * @abstract 对关键词进行排序，最长的排前面
     * @param array $keyWordsArr 热词（二维数组）
     * @return array $keyWordsArr
     */
    protected function keyWordSort($keyWordsArr){
        usort($keyWordsArr, function ($a, $b){
            $al = strlen($a[0]);
            $bl = strlen($b[0]);
            if ($al == $bl)
                return 0;
            return ($al > $bl) ? -1 : 1;
        });
        
        return $keyWordsArr;
    }
   

    /**
     * @abstract 设置内容
     * @param string $content 内容
     * @access protected
     */
    protected function setContent($content){
        $this->_content = $content;
    }
   
    /**
     * @abstract 得到热词管理的内容
     * @access protected
     */
    protected function getContent(){
        return $this->_content;
    }
   
    /**
     * @abstract 设置热词
     * @param array $keyWords
     * @access protected
     */
    protected function setKeyWords($keyWords){
        $this->_keyWords = $keyWords;
    }
   
    /**
     * @abstract 得到热词
     * @access protected
     */
    protected function getKeyWords(){
        return $this->_keyWords;
    }
   
    /**
     * @abstract 设置热词替换次数
     * @param int $times
     * @access protected
     */
    protected function setTimes($times){
        $this->_times = $times > 0 ? $times : -1;
    }
   
    /**
     * @abstract 得到替换次数
     * @access protected
     */
    protected function getTimes(){
        return $this->_times;
    }
}
```