views:

64

answers:

3

I would like to code a bbcode with SQL selection. Basically I want the user to be able to input [user]Anotheruser[/user] in a text field, which then is converted in the front-end to an URL that looks like this: http://mydomain.com/user/[userid]/anotheruser. So in order to get the userid, I'd need to include an SQL selection, and additionally an if else to find out of the other user actually exists. Can I do this with a preg_replace as usually used for creating bbcode, or do I need to do something more complex?

A: 

pre_replace should work, be careful tho. Make sure you patch any holes...watch out for sql injection in particular.

Nick
A: 

You should avoid injections POST-side, just like you should do everywhere else.

This situation is no different at all.

Lo'oris
A: 

preg_match the tag first, get the user name, execute the query (be careful and make that step safe!) and replace the whole matched string with the new url:

preg_match_all ( '#\[user\](.*?)\[/user\]#i', $text, $matches, PREG_SET_ORDER );

for ( $i = 0, $j = count( $matches ); $i < $j; $i++ )
{
    $userName = $matches[$i][1];
    $userId   = 0;

    // query example with mysqli
    $stmt = $sql->prepare( 'SELECT uid FROM users WHERE username = ? LIMIT 1' );
    $stmt->bind_param( 's', $userName );
    $stmt->execute();
    $stmt->bind_result( $userId );

    if ( $stmt->fetch() )
    {
        $text = str_replace( $matches[$i][0], "<a href=\"/user/$userId/$userName\" title=\"$userName\">$userName</a>", $text );
    }
}
poke
Good solution. To save resources, you could sanitize each match, then `implode()` the `$matches` and query for `WHERE username IN (..imploded matches..)`. That way you only need to execute *one* query.
Alec
Yeah, I just wanted to show one possible code for the SQL query. When using prepared statements, it would be even better to prepare the statement once (before the loop) and just update the parameter and execute it. Prepared statements are actually quite fast then, and I believe it would be even faster than using `IN` (and probably a bit safer, as you wouldn't need to escape yourself).
poke