2

I have an array of paths that consist of regex strings:

  $paths = [
    '/cars$',
    '.*\/cars$',
    '^cars\/.*/',
    '/trucks$',
    '.*\/trucks$',
  ];

I want to check if my current path matches something in that array, eg:

if (in_array($current_path, $paths)) {
  //Do something
}

So for example, if my URL is some-site.com/cars or some-site.com/cars/honda then I want to return something in the if statement.

But I cannot figure out how to get this working with the regex.

I investigated using preg_grep() but that seems to only work with one set of regex rules at a time.

I can get this to work with preg_match and a string, eg:

$paths = '/cars$|.*\/cars$|^cars\/.*/|/trucks$|.*\/trucks$';

if (preg_match($paths, $current_path)) {
  //Do something
}

But I will eventually have many URLs added to this list so I would prefer to use an array.

Would anyone know if there is a function that achieves this?

1
  • 1
    foreach + break. Commented May 21, 2019 at 7:52

2 Answers 2

4

If you want to know, what patterns of an array match the string, how about using array_filter.

$res = array_filter($paths, function ($v) USE ($url) {
  return preg_match('~'.$v.'~', $url);
});

See PHP demo at 3v4l.org

echo count($res)." patterns matched:\n"; print_r($res);

2 patterns matched: Array ( [0] => /cars$ 1 => .*/cars$ )

Used ~ as pattern delimiter, so you wouldn't need to escape all those url slashes.

Be aware, that .*/cars$ looks redundant, if you already match for /cars$.


If you want to break on first match, use foreach which is probably more efficient (demo).

foreach($paths AS $v) {
  if (preg_match('~'.$v.'~', $url)) {
    echo $v.' matched'; break;
  }
}

You can further easily display the matched part of $url by using $out of preg_match.

Sign up to request clarification or add additional context in comments.

2 Comments

This is really weird - I have literally the same code as you (copy, pasted it) but it returns a count of 0 each time. I don't know why.
@MeltingDog Maybe an old PHP Version? With >= 5.4 it should work.
1

I figured I could use implode() to return it to a string, eg:

$paths = [
    '/cars$',
    '.*\/cars$',
    '^cars\/.*/',
    '/trucks$',
    '.*\/trucks$',
 ];

$paths_string = implode('|', $paths);

if (preg_match($paths_string, $current_path)) {
  //Do something
}

2 Comments

That's really odd... it is working for me. Perhaps there's a different version of PHP. I though '|' was just 'OR'?
The problem is your regex is missing outer delimiters. You need something like $paths_string = '#' . implode('|', $paths) . '#'; e.g. 3v4l.org/0L6kq

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.