2

I have a replace callback method where I am trying to replace multiple string occurrences with array values accordingly.

I have passed the $parametersArray to the callback method through the use keyword as follows (the regex matches 3 elements):

$string = 'Welcome Mr MM1, MM2 MM3 to the website';
$parametersArray = array('K', 'A' , 'AD');

$line = preg_replace_callback(
    '(MM[1-9])',
    // anonymous
    function () use ($parametersArray) {
        static $paramArray = $parametersArray;
        return array_shift($paramArray);
    },
    $string
);

I am getting the below error:

Parse error: syntax error, unexpected '$parametersArray' (T_VARIABLE)

If I set the array to the static variable explicitly, I do not get the error and get the expected behavior.

Is there a problem with assigning the array as variable directly to the statically defined variable within the function?

KAD
  • 10,972
  • 4
  • 31
  • 73
  • 1
    Could you share a `$string`? Also, your callback does nothing with `$matches`, why using `preg_replace_callback` at all? BTW, also, you do not have to specify another array, see http://ideone.com/F7SoTc. – Wiktor Stribiżew Jul 13 '16 at 17:32
  • I have edited the question to add `$string`. The idea is to replace the matches with the array values accordingly. The `$matches` can be omitted from the callback method definition, you are right. – KAD Jul 13 '16 at 17:34
  • Possible duplicate of [Initialize static members in PHP](http://stackoverflow.com/questions/2934095/initialize-static-members-in-php) Alternately, http://stackoverflow.com/questions/9225632/syntax-error-while-defining-an-array-as-a-property-of-a-class – aynber Jul 13 '16 at 17:35
  • Good question but is it so hard to indent the code properly? – hek2mgl Jul 13 '16 at 17:44
  • @hek2mgl am just keeping some space for illuminaotrs... – KAD Jul 13 '16 at 17:48
  • Please remove this useless `{1}` – Casimir et Hippolyte Jul 13 '16 at 22:16

3 Answers3

1

You can init static variable like this

$line = preg_replace_callback(
    '(MM[1-9]{1})',
    // anonymous
    function ($matches) use ($parametersArray) {
        static $paramArray;

        if (null === $paramArray) {
            $paramArray = $parametersArray;
        }

        return array_shift($paramArray);
    },
    $string
);
hek2mgl
  • 152,036
  • 28
  • 249
  • 266
Invis1ble
  • 1,295
  • 2
  • 17
  • 35
  • you're kidding me... how the hell does this really work :D !! Truly, Is there any explanation for this or you just tried it?? Good catch :) – KAD Jul 13 '16 at 17:52
  • @KAD On first function call the static variable has a `null` value, because it has been just declared. On next function calls the variable already has a value from passed array. – Invis1ble Jul 13 '16 at 18:38
  • Ok @MarcB s answer helped explain this, `Static declarations are resolved in compile-time.`, so when you try setting the variable with an expression, the expression cannot be resolved until run-time.. I bet the if condition (and its content) here skipped the evaluation of the variable setting at compile-time, hence making the set action safe, please correct me if am wrong – KAD Jul 13 '16 at 18:45
1

As per the docs (See example #6): You cannot initialize a static variable with an expression:

<?php
function foo(){
    static $int = 0;          // correct 
    static $int = 1+2;        // wrong  (as it is an expression)
    static $int = sqrt(121);  // wrong  (as it is an expression too)

    $int++;
    echo $int;
}
Marc B
  • 356,200
  • 43
  • 426
  • 500
  • Can you please help us evaluate how technically @user1636505 approach fixed the problem? – KAD Jul 13 '16 at 18:49
  • undeclare vars have a null value by default. so all that did was make the `... = $var` part be a run-time assignment, instead of compile-time. that's all fine and dandy, but if that value of the var you want to initialize with ever becomes null naturally, then that assignment operation will occur again, when maybe you didn't want it to. that's nothing magical - you're now using "in-line signalling" to simulate what a normal static var creation would do, and any in-line signal is subject to abuse/failure. – Marc B Jul 13 '16 at 18:51
0

You can reference the array and use it original values in the closure afterwards. Note that the parameters get initialized at definition not when you call it - so this might work for you:

<?php

$string = 'Welcome Mr MM1, MM2 MM3 to the website';

$parametersArray = array('K', 'A' , 'AD');
$refArray =& $parametersArray;
$line = preg_replace_callback(
            '(MM[1-9]{1})',
            // anonymous
            function () use (&$refArray, $parametersArray) {
                # stays the same in every call
                # it is a copy after all
                print_r($parametersArray);
                return array_shift($refArray);
            },
            $string
);

echo $line;
# Welcome Mr K, A AD to the website
?>
Jan
  • 42,290
  • 8
  • 54
  • 79
  • 1
    I have removed the `$matches`, no need for it. This is a good approach by reference which solves the issue,, But assuming I want to keep the original array the same from external scope, is there a way to assign it statically within the function? – KAD Jul 13 '16 at 17:41
  • @KAD: Had been away, but see the updated answer with an explanation before. – Jan Jul 13 '16 at 18:35