今天实现这个如题所示的功能,通俗点讲就是在点击“回复”的时候,textarea里面出现@username,并且带链接。
这里要解决的问题是,直接在textarea中@**的时候,当数据库存在此用户的时候,也可以实现添加链接。这里的@username后面留有空格,如果没有空格则不添加链接。
v2ex的开源代码中实现了一个版本
https://github.com/livid/v2ex-gae/blob/master/v2ex/templatetags/filters.py#L151
其中的:def mentions(value):
# auto convert @username to clickable links
def mentions(value):
ms = re.findall('(@[a-zA-Z0-9\_]+\.?)\s?', value)
if (len(ms) > 0):
for m in ms:
m_id = re.findall('@([a-zA-Z0-9\_]+\.?)', m)
if (len(m_id) > 0):
if (m_id[0].endswith('.') != True):
value = value.replace('@' + m_id[0], '@<a href="/member/' + m_id[0] + '">' + m_id[0] + '</a>')
return value
else:
return value
register.filter(mentions)
基本思路是:用户名为数字和字母的组合,通过正则表达式取得后直接添加链接样式
这种比较简单,问题也比较明显:
1、不能匹配中文用户名
2、@username没有判断是否存在数据库,如果不存在添加链接则没有意义
我这里也是简化一下设计,实现的功能如下:
规定用户名username只能是字母数字和下划线,用户昵称nickname则可以是中文,在textarea中@username 显示的是username,当提交以后显示在评论栏目的时候显示的是用户的nickname。
实现的代码如下:
function mentions($value){
$pattern = '~@\w+\s~';
$match_array = [];
preg_match_all($pattern, $value, $match_array);
$count = count($match_array[0]);
for($i = 0; $i < $count; $i++){
$username = trim($match_array[0][$i], '@ ');
$res = Db::name('users')->where('username', $username)->find();
if($res){
$url = "/ebook/user/".$username;
$href = '<a target="_blank" href='.$url.'>'.$res['nickname'].'</a>';
$value = str_replace($username, $href, $value);
}
}
return $value;
}
这里使用了正则匹配与字符串替换的相关函数
Comments