Replace all urls with minified urls within a string containing mixed content

210 views Asked by At

I have string with links and iam going to extract links into an array as following

$string = "The text you want to filter goes here. http://google.com, https://www.youtube.com/watch?v=K_m7NEDMrV0,https://instagram.com/hellow/";

preg_match_all('#\bhttps?://[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#', $string, $match);

print_r($match[0]);

results

Array ( 
[0] => http://google.com 
[1] => https://www.youtube.com/watch?v=K_m7NEDMrV0 
[2] => https://instagram.com/hellow/ 
) 

Now i will use bit.ly API function gobitly() for link shorten that ends with array like this

foreach ($match[0] as $link){
    $links[] = gobitly($link);
}

the results of $links[]

Array ( 
[0] => http://t.com/1xx
[1] => http://t.com/z112
[2] => http://t.com/3431
) 

Now I want to rebuild the string and replace links to the new one to be like this

$string = "The text you want to filter goes here. http://t.com/1xx, http://t.com/z112,http://t.com/3431";
3

There are 3 answers

0
0stone0 On BEST ANSWER

Since you know the key of the url to be replaced, you can simply loop over then and use str_replace to replace each shorturl with the original;

<?php

$string = "The text you want to filter goes here. http://google.com, https://www.youtube.com/watch?v=K_m7NEDMrV0,https://instagram.com/hellow/";

preg_match_all('#\bhttps?://[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#', $string, $match);

// Shorten array
$short = [ 'http://t.com/1xx', 'http://t.com/z112', 'http://t.com/3431' ];

// For each url
foreach ($match[0] as $key => $value) {
    
    // Replace in original text
    $string = str_replace($value, $short[$key], $string);
}

echo $string;

The text you want to filter goes here. http://t.com/1xx, http://t.com/z112,http://t.com/3431

Try it online!

0
u_mulder On

You need preg_replace_callback:

$newString = preg_replace_callback(
    '#\bhttps?://[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#',
    function ($match) {
        // Use for debugging purposes
        // print_r($match);

        return gobitly($match[0]);    
    },
    $string
);

Fiddle, I used md5 instead of your function.

0
Xhynk On

You should be able to use preg_replace_callback() to manipulate the matches and return them at once, instead of extracting them and replacing them manually (which would require a bit more work, for no real reason that I can see?). Here's a quick example

$string = "The text you want to filter goes here. http://google.com, https://www.youtube.com/watch?v=K_m7NEDMrV0,https://instagram.com/hellow/";

$replaced = preg_replace_callback('#\bhttps?://[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#', function($matches){
    // This function runs on each match
    $url = $matches[0];
    
    // Do bit.ly here. This is just an example
    $url = 'url/from/bit.ly/for:'.$url;
    
    // Return the new URL (which overwrites the match)
    return $url;
}, $string );

var_dump( $replaced );

This should give you an expected output like:

string(191) "The text you want to filter goes here. url/from/bit.ly/for:http://google.com, url/from/bit.ly/for:https://www.youtube.com/watch?v=K_m7NEDMrV0,url/from/bit.ly/for:https://instagram.com/hellow/"

Of course instead of that weird concatenation I have for example purposes, you'll make a request to bit.ly or whatever API you want and use that shortened URL