为了账号安全,请及时绑定邮箱和手机立即绑定

PHP 提及系统,用户名带有空格

PHP 提及系统,用户名带有空格

PHP
慕码人8056858 2023-10-15 16:38:03
我想知道是否可以制作一个带有空格的用户名的 PHP 提及系统?我试过这个preg_replace_callback('#@([a-zA-Z0-9]+)#', 'mentionUser', htmlspecialchars_decode($r['content']))我的功能:    function mentionUser($matches) {    global $db;    $req = $db->prepare('SELECT id FROM members WHERE username = ?');    $req->execute(array($matches[1]));    if($req->rowCount() == 1) {        $idUser = $req->fetch()['id'];        return '<a class="mention" href="members/profile.php?id='.$idUser.'">'.$matches[0].'</a>';     }    return $matches[0]; 它有效,但不适用于带空格的用户名...我尝试添加\s,它有效,但效果不佳, preg_replace_callback 检测用户名和消息的其他部分,因此不会出现提及...有吗有什么解决办法吗?谢谢 !
查看完整描述

2 回答

?
白衣染霜花

TA贡献1796条经验 获得超10个赞

我知道您说过您刚刚删除了添加空格的功能,但我仍然想发布解决方案。需要明确的是,我不一定认为您应该使用此代码,因为它可能更容易使事情变得简单,但我认为它仍然应该有效。


您的主要问题是,几乎每次提及都会引起两次查找,因为@bob johnson went to the store可能是bob或bob johnson,并且如果不访问数据库就无法确定这一点。幸运的是,缓存将大大减少这个问题。


下面是一些通常可以完成您正在寻找的操作的代码。为了清晰和可重复性,我仅使用数组制作了一个假数据库。内联代码注释应该是有意义的。


function mentionUser($matches)

{

    // This is our "database" of users

    $users = [

        'bob johnson',

        'edward',

    ];

    

    // First, grab the full match which might be 'name' or 'name name'

    $fullMatch = $matches['username'];


    // Create a search array where the key is the search term and the value is whether or not

    // the search term is a subset of the value found in the regex

    $names = [$fullMatch => false];

    

    // Next split on the space. If there isn't one, we'll have an array with just a single item

    $maybeTwoParts = explode(' ', $fullMatch);

    

    // Basically, if the string contained a space, also search only for the first item before the space,

    // and flag that we're using a subset

    if (count($maybeTwoParts) > 1) {

        $names[array_shift($maybeTwoParts)] = true;

    }


    foreach ($names as $name => $isSubset) {

        

        // Search our "database"

        if (in_array($name, $users, true)) {

            

            // If it was found, wrap in HTML

            $ret = '<span>@' . $name . '</span>';

            

            // If we're in a subset, we need to append back on the remaining string, joined with a space

            if ($isSubset) {

                $ret .= ' ' . array_shift($maybeTwoParts);

            }


            return $ret;

        }

    }

    

    // Nothing was found, return what was passed in

    return '@' . $fullMatch;

}


// Our search pattern with an explicitly named capture

$pattern = '#@(?<username>\w+(?:\s\w+)?)#';


// Three tests

assert('hello <span>@bob johnson</span> test' === preg_replace_callback($pattern, 'mentionUser', 'hello @bob johnson test'));

assert('hello <span>@edward</span> test' === preg_replace_callback($pattern, 'mentionUser', 'hello @edward test'));

assert('hello @sally smith test' === preg_replace_callback($pattern, 'mentionUser', 'hello @sally smith test'));



查看完整回答
反对 回复 2023-10-15
?
猛跑小猪

TA贡献1858条经验 获得超8个赞

试试这个正则表达式:

/@[a-zA-Z0-9]+( *[a-zA-Z0-9]+)*/g

它会首先找到一个 at 符号,然后尝试找到一个或多个字母或数字。它将尝试找到零个或多个内部空格以及其后的零个或多个字母和数字。

我假设用户名仅包含 A-Za-z0-9 和空格。


查看完整回答
反对 回复 2023-10-15
  • 2 回答
  • 0 关注
  • 79 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信