PHP递归语法

PHP递归语法

问题描述:

I've never done recursions before and I feel I might be missing something. This code works but seems more "wordy" than it needs to be. Seems like I've seen people doing do..while's for recursion, but I'm not sure how/if it would apply here.

resolve($array) is supposed to replace any "{% tags %}" with the appropriate string from the same $array, and repeat the process in case of nesting. Simplified as best I could - hope this makes sense:

<?php

$strings = [
    "title":"My Program",
    "first_string":"<b>{% title %}:</b> The second_string text is {% second_string %}",
    "second_string"=>"Hello, World! Do you like {% title %}?"
];

function resolve($strings) {

    $regex = "/{% ([^{}]*?) %}/"; //RegEx for getting {% tags %}

    foreach($strings as $str_key=>$str_val) {
        //if the string has any {% tags %}...
        if(preg_match_all($regex,$str_val,$tmp_tags_arr)) {
            list($tags,$tagNames) = $tmp_tags_arr;
            foreach($tagNames as $tag_key=>$tag_name) //for every tagname...
                $strings[$str_key] = str_replace(
                    $tags[$tag_key],
                    $strings[$tag_name],
                    $strings[$str_key]
                    ); //replace the whole {% tag %} with appropriate value
        }
    }

    /*****This part just seems overly redundant******/

    //Rerun all the $strings to check if there are still unresolved {% tags %}
    foreach($strings as $str_key=>$str_val)
        if(preg_match_all($regex,$str_val,$tags))
            $strings = resolve($strings);

    return $strings;

}

var_dump(resolve($strings));
// Returns:
// array (size=3)
//   'title' => string 'My Program' (length=10)
//   'first_string' => string '<b>My Program:</b> The second_string text is Hello, World!' (length=58)
//   'second_string' => string 'Hello, World! Do you like My Program?' (length=13)

?>

My question is: what is the more appropriate way to do a recursion like this?

Edit:

$strings['first_string'] references 'title' and 'second_string', but 'second_string' includes a {% tag %} itself... hence the need for recursion.

No recursion necessary since the keys must be unique and we know what they are, just loop through those. As str_replace takes arrays, you can replace on the entire array each time through the loop:

foreach(array_keys($strings) as $tag) {
    $strings = str_replace("{% $tag %}", $strings[$tag], $strings);
}
print_r($strings);

The value of array_keys($strings) is 'title', 'first_string', 'second_string', so the loop proceeds like this:

Iteration 1: Searches for {% title %} in the entire array and replaces it with its value from $strings

$strings = [
    "title"=>"My Program",
    "first_string"=>"<b>My Program:</b> The second_string text is {% second_string %}",
    "second_string"=>"Hello, World! Do you like My Program?"
];

Iteration 2: Searches for {% first_string %} in the entire array and replaces it with its value from $strings

$strings = [
    "title"=>"My Program",
    "first_string"=>"<b>My Program:</b> The second_string text is {% second_string %}",
    "second_string"=>"Hello, World! Do you like My Program?"
];

Iteration 3: Searches for {% second_string %} in the entire array and replaces it with its value from $strings

$strings = [
    "title"=>"My Program",
    "first_string"=>"<b>My Program:</b> The second_string text is Hello, World! Do you like My Program?",
    "second_string"=>"Hello, World! Do you like My Program?"
];

DEMO