Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 7 of 7
  1. #1
    New Coder
    Join Date
    Jun 2006
    Posts
    12
    Thanks
    0
    Thanked 0 Times in 0 Posts

    problem with preg_replace()

    Hello, I have a problem using preg_replace for my bbcode. I want it to search for a color (i.e. "Red", "Blue", etc.) in the URL it is turning into a link, and then make that link that color.

    The bbcode links are formed like usual: [ url=http://mysite.com/]text[/url]

    The problem occurs when I have two links, like this:

    Code:
    [ url=http://mysite.com/Red/page.php]Link 1[/url] blah blah blah [ url=http://mysite2.com/Green/page2.php]Link 2[/url]
    What happens is that PHP thinks that everything from the first http to the end of the second URL is all one URL. To help explain:

    [ url=http://mysite.com/Red/page.php]Link 1[/url] blah blah blah [ url=http://mysite2.com/Green/page2.php]Link 2[/url]

    It thinks that all the orange in there is all one URL, so it makes one link with the href attribute being that entire orange blob of text.

    My preg_replace code for that part is this:

    PHP Code:
    function parse($string) {
    global 
    $allcolors// contains all colors to match (Red, Blue, Green, etc.)
        
    foreach($allcolors as $color) {
        
    // colors links accordingly if they have one of our colors in their url
            
    $preg_find[] = '/\[url\=(.*?)' $color '(.*?)\](.*?)\[\/url\]/is';
            
    $preg_replace[] = '<a href="$1' $color '$2" style="color: ' $color ';">$3</a>';
    // ... some more code for bbcode ...
    $string preg_replace($preg_find$preg_replace$string);
    return 
    $string
    I can't figure out how to avoid it! Any help or suggestions are appreciated much. Thanks!

  • #2
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,987
    Thanks
    4
    Thanked 2,660 Times in 2,629 Posts
    It works otherwise right? I reaaalllly don't want to do any pattern matching right now -_-.
    Anyway, what you are experiencing is PHP's greedyness. Simple fix, on your pattern modifiers (ie: '/^a.../si' the 'si' are your modifiers), add a 'U' to tell PHP to not be greedy. By default, it will seek anything between the two possible options you are giving it, including more calls. Try that, see if that fixes if for you.
    PHP Code:
    header('HTTP/1.1 420 Enhance Your Calm'); 

  • #3
    New Coder
    Join Date
    Jun 2006
    Posts
    12
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Just tried it, same exact thing happens.

    It works fine when there is only one link. It also works fine when I comment out the color-related code and let the link be parsed as a normal link (the normal link code was not shown in my first post).

    Out of curiosity I added the U to the normal link parsing, and commented out the color-related parsing to see what would happen, and it actually seemed like it did the opposite of the desired effect -- the same problem I initially had occurs (it thinks the URL is that huge blob of text), only with the normal link parsing and not the color parsing.

    I'm not too familiar with the modifiers; is there a modifier that does the opposite of whatever U does? It seems like that might help.

  • #4
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,987
    Thanks
    4
    Thanked 2,660 Times in 2,629 Posts
    What I can tell you (after testing it), is its not a greedyness thing:
    PHP Code:
    function parse($string)
    {
        
    $allcolors = array('Red''Green');
        foreach(
    $allcolors as $color) {
        
    // colors links accordingly if they have one of our colors in their url
            
    $preg_find[] = '/\[url\=(.*?)' $color '(.*?)\](.*?)\[\/url\]/is';
            
    $preg_replace[] = '<a href="$1' $color '$2" style="color: ' $color ';">$3</a>';
    // ... some more code for bbcode ...
        
    }
    $string preg_replace($preg_find$preg_replace$string);
    return 
    $string;  
    }

    $str "[url=http://mysite.com/Red/page.php]Link 1[/url] blah blah blah [url=http://mysite2.com/Green/page2.php]Link 2[/url]";

    echo 
    parse($str); 
    This results in this:
    Link 1 blah blah blah Link 2
    Where link 1 goes to: http://myslite.com/Red/page.php and http://mysite2.com/Green/page2.php.
    So this block of code itself is alright. I'm thinking the problem in this case is it is interfering with the already existing url tag built into the system. If this is the case, you can probably get around modifying it by placing this as a higher priority in replacement than the url tag. If that still doesn't work, you will need to change the url code to reflect the possibility of a colour addition.

    Try those out, see if either of them fix the problem for you.
    PHP Code:
    header('HTTP/1.1 420 Enhance Your Calm'); 

  • #5
    New Coder
    Join Date
    Jun 2006
    Posts
    12
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Okay, after some testing I've figured out what the problem is, but I don't know how to fix it.

    The code block you gave me only works when the colors in the array are in the same order as the links in the string. So if you change the array from
    PHP Code:
    $allcolors = array('Red''Green'); 
    to
    PHP Code:
    $allcolors = array('Green''Red'); 
    it doesn't work anymore.

  • #6
    Super Moderator Inigoesdr's Avatar
    Join Date
    Mar 2007
    Location
    Florida, USA
    Posts
    3,647
    Thanks
    2
    Thanked 406 Times in 398 Posts
    Here, try this:
    PHP Code:
    function parse($string)
    {
        
    $allcolors = array('Red''Green''Black'); // this is set elsewhere, apparently
        
    $allcolors = !empty($allcolors) ? implode('|'$allcolors) : 'Red'// make sure allcolors always has a value
        
    $replace = array('~\[url=(https?://.*?/)(' $allcolors ')(/.*?)\](.*?)\[/url\]~si' => '<a href="\\1\\2\\3" style="color: \\2;">\\4</a>');
        
    $string preg_replace(array_keys($replace), array_values($replace), $string);
        return 
    $string;  
    }

    $str "[url=http://mysite.com/Red/page.php]Link 1[/url] blah blah blah [url=http://mysite2.com/Green/page2.php]Link 2[/url] blah blah blah [url=http://mysite2.com/Black/page2.php]Link 3[/url]";

    echo 
    parse($str); 
    I changed the delimiter to a tilde to avoid having to escape all of the forwardslashes.

    If you're only doing the color replace on the string you don't really need a function(or array of the replacements), unless you're replacing the same thing in multiple strings. If it's just one you can do something like this:
    PHP Code:
    $str "[url=http://mysite.com/Red/page.php]Link 1[/url] blah blah blah [url=http://mysite2.com/Green/page2.php]Link 2[/url] blah blah blah [url=http://mysite2.com/Black/page2.php]Link 3[/url]";
    $allcolors = array('Red''Green''Black'); // this is optional, and set elsewhere, apparently
    $allcolors = !empty($allcolors) ? implode('|'$allcolors) : 'Red'// make sure allcolors always has a value
    $string preg_replace('~\[url=(https?://.*?/)(' $allcolors ')(/.*?)\](.*?)\[/url\]~si''<a href="\\1\\2\\3" style="color: \\2;">\\4</a>'$str);
    echo 
    $string

  • #7
    New Coder
    Join Date
    Jun 2006
    Posts
    12
    Thanks
    0
    Thanked 0 Times in 0 Posts
    Awesome! Had to change it a little, but it works perfect! Thanks a bunch!

    Oh, and I actually did need to use it in a function, because I have a big parse function for parsing all text that needs to, well, be parsed, and this was only a small piece of it.

    Thanks so much again!


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •