-2

I create this pattern

$pattern = "/<a href='(?<href>.+?)'>(?<name>.+?)<\/a>/i";

And i have this example,

$string = "<a href='https://www.php.net/'>https://www.php.net/</a> 
<a href='https://stackoverflow.com/'>https://stackoverflow.com/</a> 
<a href='https://www.google.com/'>https://www.google.com/</a>";

Using this, i can find the matches and extract the href, and the name.

preg_match_all($pattern, $string, $matches);

Array
(
    [0] => Array
        (
            [0] => https://www.php.net/
            [1] => https://stackoverflow.com/
            [2] => https://www.google.com/
        )

    [href] => Array
        (
            [0] => https://www.php.net/
            [1] => https://stackoverflow.com/
            [2] => https://www.google.com/
        )

    [1] => Array
        (
            [0] => https://www.php.net/
            [1] => https://stackoverflow.com/
            [2] => https://www.google.com/
        )

    [name] => Array
        (
            [0] => https://www.php.net/
            [1] => https://stackoverflow.com/
            [2] => https://www.google.com/
        )

    [2] => Array
        (
            [0] => https://www.php.net/
            [1] => https://stackoverflow.com/
            [2] => https://www.google.com/
        )

)

The problem is when I use the preg_replace, since the pattern is the same, it changes the same information for all the URL, and i need to change only the name and preserve the rest of the information accordingly.

Using,

if(preg_match_all($pattern, $string, $matches))
{
    $string = preg_replace($pattern, "<a href='$1'>Name</a>", $string);

}

I can get the results from the groups, and preserve the first part of the href. But if i try to change the name, it's the same for all results.

If I try to use "str_replace", I can have different results as intended, but this gave me 2 problems. One is that if i try to replace the name, i also change the href, and if i have similar URL with "more slashes" it will change the match part, and leave the rest of the information.

In a database I have list of URL with a column that have names, and if the string match any row in the table I need to change the name accordingly and preserve the href.

Any help?

Thank you.

Kind regards!

BlaTimba
  • 15
  • 1
  • 6
  • Looks a bit like https://stackoverflow.com/a/52989605/2943403 , https://stackoverflow.com/a/54324960/2943403 , https://stackoverflow.com/a/45806855/2943403 , https://stackoverflow.com/a/45685528/2943403 , https://stackoverflow.com/a/48730001/2943403 , https://stackoverflow.com/a/48068407/2943403 – mickmackusa Apr 13 '19 at 12:22

1 Answers1

0

I'll assume you retrieve rows from your database with a format such as this:

$rows = [
  ['href' => 'https://www.php.net/', 'name' => 'PHP.net'],
  ['href' => 'https://stackoverflow.com/', 'name' => 'Stack Overflow'],
  ['href' => 'https://www.google.com/', 'name' => 'Google']
];

From there, you can first create an href -> name map using a loop or array_reduce:

$rows_by_href = array_reduce($rows, function ($rows_by_href, $row) {
  $rows_by_href[$row['href']] = $row['name'];
  return $rows_by_href;
}, []);

You can then use preg_replace_callback to replace each match with its associated name if it exists:

$result = preg_replace_callback($pattern, function ($matches) use ($rows_by_href) {
  return "<a href='" . $matches['href'] . "'>" 
    . ($rows_by_href[$matches['href']] ?? $matches['name']) 
    . "</a>";
}, $string);

echo $result;

Demo: https://3v4l.org/IY6p0

Note that this assumes the URLs (href) within $string are formatted the exact same way as the ones coming from your DB. Otherwise you can rtrim the trailing slashes or do anything else you need beforehand.

Also note that it's usually a bad idea to parse HTML with regular expressions if you can avoid it. A DOM parser is way more appropriate, unless you have to parse a string that comes from a comment or forum post or something not in your control.

Jeto
  • 14,596
  • 2
  • 32
  • 46