I'm trying to figure out how to identify the order of occurrences for matched regex groups. but can't find any such functionality. Yet, I'm sure it has to be there and I'm just doing something wrong...
So far I have this:
$string = "SELECT id, title FROM table WHERE id = ?d AND qwe=?s";
$pattern = '/(\?+[sdf]{1})/i';
$data = array(111, 222, 333);
$inc = 0;
function callback($matches) {
global $inc, $data;
$inc++;
switch ($matches[0]) {
case '?s':
return '`'.$data[$inc].'`';
case '?d':
return (int) $data[$inc];
case '?f':
return (double) $data[$inc];
}
}
print_r(preg_replace_callback($pattern, 'callback', $string));
It works, but that thing with $inc is certainly not the way to go...
I want to avoid using $inc at all here. Is there a way to know the order of occurrences when these regex groups are matched? That's what I'm trying to do. So, maybe I will have not only the matches, but a number that will tell me what match this is in order.
Is there a better solution to this problem?
You mix up two things: multiple matches and groups. When you have groups, you can access them (by name or by ID). When you have multiple matches (and when you use preg_replace..., you actually have the regex engine find all non-overlapping matches in the text and process them individually), the regex engine does not know if it is the first, or second, etc. So, there is no other way with the current input data than using a counter.
If you can change the input data, I suggest using a key-value $data array where keys will be equal to the variables you want to match in the text (s, f, or d). In order to access them from inside a match, you need to capture [sfd] in your regex, i.e. you need to wrap that character class with a capturing group.
Use
$string = "SELECT id, title FROM table WHERE id = ?d AND qwe=?s";
$pattern = '/\?+([sdf])/i';
$data = array("s" => 111, "d" => 222, "f" => 333);
$inc = 0;
echo preg_replace_callback($pattern, function ($matches) use ($data) {
switch ($matches[0]) {
case '?s':
return '`'.$data[$matches[1]].'`';
case '?d':
return (int) $data[$matches[1]];
case '?f':
return (double) $data[$matches[1]];
}
}, $string);
See the PHP demo.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With