Search code examples
phpcallbackpreg-match-allpreg-replace-callback

PHP Understanding callbacks - difference between preg_replace_callback() and preg_match_all()


I am a bit confused on the use of preg_replace_callback()

I have a $content with some URLs inside .

Previously I used

 $content = preg_match_all( '/(http[s]?:[^\s]*)/i', $content, $links );


 foreach ($links[1] as $link ) {
            // we have the link. find image , download, replace the content with image
            // echo '</br>LINK : '. $link;
            $url = esc_url_raw( $link );
            $url_name = parse_url($url); 
            $url_name = $description = $url_name['host'];// get rid of http://..
            $url = 'http://somescriptonsite/v1/' .  urlencode($url)   . '?w=' . $width ;
            } 

    return $url;

But what I really need is to REPLACE the original URL with my parsed URL...

So I tried the preg_replace_callback:

function o99_simple_parse($content){

$content = preg_replace_callback( '/(http[s]?:[^\s]*)/i', 'o99_simple_callback', $content );


return $content;
}

and :

function o99_simple_callback($url){
    // how to get the URL which is actually the match? and width ??
        $url = esc_url_raw( $link );
        $url_name = parse_url($url); 
        $url_name = $description = $url_name['host'];// get rid of http://..
        $url = 'http://something' .  urlencode($url)   . '?w=' . $width ; 
        return $url; // what i really need to replace 
    }

I assumed that the callback will work in a way that EVERY match will call the callback (recursively ?) and get back results , thus allowing for to replace on-the-fly the URLS in $content with the parsed $url from o99_simple_callbac().

But another question here (and especially this comment) triggered my doubts .

If the preg_replace_callback() actually pass the whole array of matches , then what is actually the difference between what I used previously ( preg_match_all() in first example ) and the callback example ?

What am I missing / misunderstanding ?? What would be the correct way of replacing the URLS found in $content with the parsed urls ?


Solution

  • It does not pass all matches, but invokes the callback for each match. The callback won't receive a single string parameter, but a list of strings. $match[0] is the whole match, and $match[1] the first capture group (what's in your regex between the first parens).

    So this is how your callback should look:

    function o99_simple_callback($match){
        $url = $match[1];
        //$url = esc_url_raw( $link );
        $url_name = parse_url($url); 
        $url_name = $description = $url_name['host'];// get rid of http://..
        $url = 'http://something' .  urlencode($url)   . '?w=' . $width ; 
        return $url; // what i really need to replace 
    }
    

    Please also see the manual examples on preg_replace_callback