How do I access a variable inside of preg_replace_callback?
Asked Answered
E

2

17

I'm trying to replace {{key}} items in my $text with values from a passed array. but when I tried adding the print_r to see what was going on I got a Undefined variable: kvPairs error. How can I access my variable form within the preg_replace_callback?

public function replaceValues($kvPairs, $text) {
    $text = preg_replace_callback(
        '/(\{{)(.*?)(\}})/',
        function ($match) {
            $attr = trim($match[2]);
            print_r($kvPairs[strtolower($attr)]);
            if (isset($kvPairs[strtolower($attr)])) {
                return "<span class='attr'>" . $kvPairs[strtolower($attr)] . "</span>";
            } else {
                return "<span class='attrUnknown'>" . $attr . "</span>";
            }
        },
        $text
    );
    return $text;
}

Update:

I've tried the global scope thing, but it doesn't work either. I've added 2 print statements to see whats doing on, one inside and one outside the preg_replace_callback.

public function replaceValues($kvPairs, $text) {
    $attrTest = 'date';
    print_r("--" . strtolower($attrTest) . "--" . $kvPairs[strtolower($attrTest)] . "--\n");
    $text = preg_replace_callback(
        '/(\{{)(.*?)(\}})/',
        function ($match) {
            global $kvPairs;
            $attr = trim($match[2]);
            print_r("==" . strtolower($attr) . "==" . $kvPairs[strtolower($attr)] . "==\n");
            if (isset($kvPairs[strtolower($attr)])) {
                return "<span class='attr'>" . $kvPairs[strtolower($attr)] . "</span>";
            } else {
                return "<span class='attrUnknown'>" . $attr . "</span>";
            }
        },
        $text
    );
    return $text;
}

The output I get is:

--date--1977-05-20--
==date====
Exhalant answered 8/5, 2013 at 16:47 Comment(0)
E
51

As your callback function is a closure, you can pass extra arguments via use

function ($match) use ($kvPairs) {
    ...
}

better than polluting the global space

Earache answered 8/5, 2013 at 16:52 Comment(2)
I would like to manipulate $kvPairs for the next match, ist this possible or do I need a global variable for it?Empower
If you need to manipulate $kvPairs within the callback then you pass it by reference: function ($match) use (&$kvPairs) { ... }Earache
R
0

Your script can be modernized and refined to allow access to globally scoped values without use(). Arrow function syntax from PHP7.4 allows access to variables which were declared outside of the callback's scope.

I've removed some unnecessary escaping and capture groups from your pattern. Adding some space-consuming logic on either side of the capture group affords the omission of trim() calls on the captured string.

Code: (Demo)

function replaceValues(array $kvPairs, string $text): string
{
    return preg_replace_callback(
               '/{{\s*(.*?)\s*}}/',
                fn($m) => isset($kvPairs[strtolower($m[1])])
                    ? '<span class="attr">' . $kvPairs[strtolower($m[1])] . '</span>'
                    : '<span class="attrUnknown">' . $m[1] . '</span>',
                $text
            );
}

Otherwise, this is a duplicate of Callback function using variables calculated outside of it.

Realtor answered 25/3, 2023 at 5:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.