1

I'm fetching a lot of product rows from the database.

Some of these rows contains a domain name (eg. google.com) which I'd like to be removed (trim) from the string before outputting it. NOTE: There are multiple TLD's (.se, .fi., .net, .org ...)

At first, I will fetch all domain names from domain table into own array and then with preg_match(), run a test whether the string contains a specific domain or not. If domain is not found from product row, nothing needs to be trimmed.

Here's what the domains array will look like:

[0] => Array
        (
            [domain] => google.com
        )
 [1] => Array
        (
            [domain] => google.se
        )

Here's an example of rows outputted from the database:

Product 1 - Test purposes 1
Product 2 - Test purposes 2 google.com
Product 2 - Test purposes 2 google.se

And underneath is what I've tried so far:

<?php
...
$table = [];

# loop through all rows from the database
while ($row = $stmt->fetch()) {
    # loop through all domains
    foreach($domains as $domain) {
        if(preg_match("/{$domain['domain']}/i", $row['product'],$matches, PREG_OFFSET_CAPTURE)) {
            $trimmed = str_replace($domain['domain'], '', $row['product']) ;
            $table[$i]['product'] = $trimmed;
        } else {
            $table[$i]['product'] = $row['product'];
        }
    }
}

This does ignore all the domains it finds and just uses the original $row['product'] instead of trimming the domain name from the $row['product'].

2
  • So, what's the problem? Commented Mar 5, 2019 at 7:24
  • The regex above doesn't remove the domain name from the $row['product'], it returns the original. Commented Mar 5, 2019 at 7:25

2 Answers 2

1

Here is one way to do it, just set the $multi variable to whatever you are using....

// (?) could have more than one domain match true / false

$multi = FALSE;

while ( $row = $stmt->fetch ( ) )
{
    // loop through all domains

    $trimmed = $row['product'];

    foreach ( $domains as $domain )
    {
        if( preg_match ( "/{$domain['domain']}/i", $trimmed ) )
        {
            $trimmed = str_replace ( $domain['domain'], '', $trimmed );

            if ( $multi === FALSE )
            {
                break;
            }
        }
    }

    $table[$i]['product'] = $trimmed;
}
Sign up to request clarification or add additional context in comments.

2 Comments

But one thing about this... I still don't see where you are setting or increasing the variable ($i) in array $table[$i]....
Accidentally ommited it from the source code. This seems to do the trick, I'll accept this as an answer. Cheers! :)
0

Summary

This is a beautiful one. You're going to love the answer.

Add the following line before the } else {:

continue 2;

Explanation

Since you're doing a double loop, if the domain that is matching is not the last domain, it will override the domain it did match. Thus you need to go straight to the next row, not just the next domain once you've found a match.

Code

<?php

$domains = [
    ["domain" => "google.com"],
    ["domain" => "google.se"]
];

$rows = [
    ["product" => "Product 1 - Test purposes 1"],
    ["product" => "Product 2 - Test purposes 2 google.com"],
    ["product" => "Product 2 - Test purposes 2 google.se"],
];

$table = [];

# loop through all rows from the database
foreach($rows as $id => $row){
    # loop through all domains
    foreach($domains as $domain) {
        if(preg_match("/{$domain['domain']}/i", $row['product'],$matches, PREG_OFFSET_CAPTURE)) {
            $trimmed = str_replace($domain['domain'], '', $row['product']) ;
            $table[$id]['product'] = $trimmed;
            continue 2;
            //As soon as you hit a match, go to the next *row*.
            //Don't try to match any more domains.
        } else {
            $table[$id]['product'] = $row['product'];
        }
    }
}

var_dump($table);

Caveats

This assumes that you only have one domain match per row.

https://3v4l.org/Oo2Ie

2 Comments

but that does nothing to stop multiple }else{ blocks from being run when there is no match, that }else{ in the domain loop needs to moved out of the domain loop and a if() question added after that loop if $trimmed is still empty, ie; no match was found...
Ya, I would probably restructure the loop also, but continue 2; was the least invasive solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.