A better way to replace emoticons in PHP?

2019-01-14 19:28发布

问题:

Right now I am using this function for emoticons:

function emoticons($text) {
        $icons = array(
                ':)'    =>  '<img src="/images/blank.gif" alt="smile" class="icon_smile" />',
                ':-)'   =>  '<img src="/images/blank.gif" alt="smile" class="icon_smile" />',
                ':D'    =>  '<img src="/images/blank.gif" alt="smile" class="icon_laugh" />',
                ':d'    =>  '<img src="/images/blank.gif" alt="laugh" class="icon_laugh" />',
                ';)'    =>  '<img src="/images/blank.gif" alt="wink" class="icon_wink" />',
                ':P'    =>  '<img src="/images/blank.gif" alt="tounge" class="icon_tounge" />',
                ':-P'   =>  '<img src="/images/blank.gif" alt="tounge" class="icon_tounge" />',
                ':-p'   =>  '<img src="/images/blank.gif" alt="tounge" class="icon_tounge" />',
                ':p'    =>  '<img src="/images/blank.gif" alt="tounge" class="icon_tounge" />',
                ':('    =>  '<img src="/images/blank.gif" alt="sad face" class="icon_sad" />',
                ':o'    =>  '<img src="/images/blank.gif" alt="shock" class="icon_shock" />',
                ':O'    =>  '<img src="/images/blank.gif" alt="shock" class="icon_shock" />',
                ':0'    =>  '<img src="/images/blank.gif" alt="shock" class="icon_shack" />',
                ':|'    =>  '<img src="/images/blank.gif" alt="straight face" class="icon_straight" />',
                ':-|'   =>  '<img src="/images/blank.gif" alt="straight face" class="icon_straight" />',
                ':/'    =>  '<img src="/images/blank.gif" alt="straight face" class="icon_straight" />',
                ':-/'   =>  '<img src="/images/blank.gif" alt="straight face" class="icon_straight" />'
        );
        return strtr($text, $icons);
    }

But if you enter a link the :/ part of http:// gets replaced:

Same with code (4 spaces in front of each line to create code box), but for some reason a simple ) gets replaced (with a wink) as well:

Is there a better solution to this than replacing all of the icons like this? It obviously doesn't work good. I have searched on Google a lot and haven't found any better way. I also tried putting a space before each emoticon in the associative array above but that doesn't work if you just enter a :) without anything before it.

回答1:

You can use the preg_replace function and then use word boundaries in the regular expression.

 foreach($icons as $icon=>$image) {
      $icon = preg_quote($icon);
      $text = preg_replace("~\b$icon\b~",$image,$text);
 }

You need to use word boundaries and not white space because this will take care of the start and end points to. Needing a space before means that just a :) won't be found.



回答2:

Regular expressions are slow for this if the text is big, as much as i like them, you should only insert an icon if it's surrounded by spaces, that way your users won't riot when trying to write urls.



回答3:

I'm not sure whether it will work or not, but I'd try to put some extra spaces like this:

function emoticons($text) {
    $icons = array(
            ' :) '    =>  ' <img src="/images/blank.gif" alt="smile" class="icon_smile" /> ',
            ' :-) '   =>  ' <img src="/images/blank.gif" alt="smile" class="icon_smile" /> ',
            ' :D '    =>  ' <img src="/images/blank.gif" alt="smile" class="icon_laugh" /> ',
            ' :d '    =>  ' <img src="/images/blank.gif" alt="laugh" class="icon_laugh" /> ',
            ' ;) '    =>  ' <img src="/images/blank.gif" alt="wink" class="icon_wink" /> ',
            ' :P '    =>  ' <img src="/images/blank.gif" alt="tounge" class="icon_tounge" /> ',
            ' :-P '   =>  ' <img src="/images/blank.gif" alt="tounge" class="icon_tounge" /> ',
            ' :-p '   =>  ' <img src="/images/blank.gif" alt="tounge" class="icon_tounge" /> ',
            ' :p '    =>  ' <img src="/images/blank.gif" alt="tounge" class="icon_tounge" /> ',
            ' :( '    =>  ' <img src="/images/blank.gif" alt="sad face" class="icon_sad" /> ',
            ' :o '    =>  ' <img src="/images/blank.gif" alt="shock" class="icon_shock" /> ',
            ' :O '    =>  ' <img src="/images/blank.gif" alt="shock" class="icon_shock" /> ',
            ' :0 '    =>  ' <img src="/images/blank.gif" alt="shock" class="icon_shack" /> ',
            ' :| '    =>  ' <img src="/images/blank.gif" alt="straight face" class="icon_straight" /> ',
            ' :-| '   =>  ' <img src="/images/blank.gif" alt="straight face" class="icon_straight" /> ',
            ' :/ '    =>  ' <img src="/images/blank.gif" alt="straight face" class="icon_straight" /> ',
            ' :-/ '   =>  ' <img src="/images/blank.gif" alt="straight face" class="icon_straight" /> '
    );
    return strtr($text, $icons);
}


回答4:

I'd recommend two libraries:

Emojify: https://github.com/HallgrenNetworks/emojify

PHP Emoji: https://github.com/iamcal/php-emoji

These will deal with these cases for you.



回答5:

I think using regular expressions instead of just defining your emoticons. This could look like

// replaces a :) when it is surrounded by whitespaces
return preg_replace('/\s:)\s/', '<img ...>', $text);