解析有限大小的数据库表内容的文本

时间:2010-02-03 16:16:04

标签: php javascript jquery mysql

我有一个“人”的MySQL表作为网站的一部分,例如:

| people_id  | firstname  | lastname    |
-----------------------------------------
| 1          | John       | Lennon      |
| 2          | Paul       | McCartney   |
| 3          | George     | Harrison    |
| 4          | Ringo      | Starr       |
| .          | .          | .           |

我的桌子有大约2000行。

我在网站上也有一个“新闻”部分。通常,这些新闻项目包含对“人”的引用,例如

  约翰列侬和保罗麦卡特尼写道   一些最受欢迎的歌曲   摇滚音乐史。

是否可以(或合理/可取)自动解析每个新闻项目以查找数据库中的“人员”,然后将其转换为链接。因此,例如,上面的文本将变成这个(或功能相同的东西):

<a href="/people/1>John Lennon</a> and <a href="/people/2">Paul McCartney</a> wrote some of the most popular songs in the history of rock music.

最好的方法是什么?我在php中使用正则表达式做了一些失败的尝试,但我想这不是最好的方法。我对javascript(及其框架)了解不多,但如果有意义的话,我会很乐意使用它。

这不是网站的基本功能(但我觉得这将是一个很好的补充)所以我宁愿省略这样的功能,而不是大幅增加页面加载时间。

修改

我在最初的问题中省略了一些细节,以保持长度。

事实上,它是足球俱乐部的网站 - 所有“人”都是网站的成员,可以登录,添加和编辑新闻报道(例如,匹配报告),其中经常提到其他“人”。所以不只是我添加了新闻故事 - 他们可以被(大约)2000个其他用户添加。

虽然会员资格受到限制,因为人们必须在加入之前获得批准,但系统必须能够应对诸如名字不寻常的人之类的复杂情况,并且有一些人具有相同名称的实例

我已经实现了一种解决方案,其中我使用一种专有代码来标记/关闭人的名字(例如[p = 1] John Lennon [/ p])但我发现,在2000年网站的用户,只有少数人使用这个。

对于它的价值,该网站是www.ouafc.com,新闻报道的一个例子是www.ouafc.com/news/312。

2 个答案:

答案 0 :(得分:2)

我对php不太了解,但是这里有一个快速的JavaScript使用jQuery 1.4:

<div id="maindiv">
   John Lennon and Paul McCartney wrote some of the most popular songs in the history of rock music.
</div>


<script>
   $(document).ready(function(){
       myPage.linkify($("#maindiv"));
    })

var myPage = {
    map: {
            "John Lennon": 1,
            "Paul McCartney": 2,
            "Rock Music": 3
         },

    linkify: function(domEl){
        var htmlcopy = domEl.html();

        function buildLink(txt, loc){
            return '<a "href = /blah/'+loc+'>'+txt+'</a>';
        }

        for(i in myPage.map){
           var tmpStr = new RegExp(i,"gi");
           htmlcopy = htmlcopy.replace( tmpStr, buildLink(i, myPage.map[i]) );
       }

       domEl.html(htmlcopy);
    }
 }
</script>

myPage.map将在数据库的服务器端构建。这也可能是对Ajax函数的回调(可以抓取地图),这样就不会阻止页面的其余部分做它的事情。

答案 1 :(得分:1)

您最好的选择是以某种方式手动标记新闻帖子,以指明名称何时出现。这是防止错过名称或不正确解析名称的唯一方法,并且避免了从数据库中扫描每个可能名称的每个新闻故事的巨大处理要求。

也许是像twittery一样的语法:

@[John Lennon] and @[Paul McCartney] wrote some of the most popular songs in the history of rock music.

然后,当您想要显示新闻报道时,通过自定义的markdown - 样式函数运行它。它可以解析那些标记,找到匹配的DB记录,并生成链接。

在将新闻报道插入数据库之前将@ []标记转换为链接会更有效率,但这会更紧密地耦合 - 如果用户被删除或其ID发生变化,则链接断开。存储@ []也使编辑故事更容易。

更新

如果您必须自动检测到名称并将其转换为链接,则可以通过相当严重的性能损失来实现,只有在添加更多名称时才会增加:

function linkify_names($news) {
  $people = query('select people_id, firstname, lastname from people');

  $from = $to = array();
  foreach ($people as $person) {
    $name = "$person->firstname $person->lastname";
    // TODO - escape regex chars in $name?

    // match [boundary]$name[boundary], case insensitive
    $from[] = "/(\b)($name)(\b)/i";

    // include boundaries in replacement; maintain case of found name
    $to[] = '$1<a href="/people/' . $person->people_id .'">$2</a>$3';
  }

  return preg_replace($from, $to, $news);
}

不同之处在于,您不必只查找标有@ []标签的名称,而是必须查找所有名称,并详尽地搜索每个名称。您不能依赖简单的正则表达式来查找新闻文档正文中的名称。