0

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.

7
  • sorry, i fixed the function... resolve() is called inside itself. Commented Aug 5, 2014 at 17:49
  • So what value of $strings would cause the recursion to happen? Variable variables? Like {% {% variable %} %}? This makes no sense Commented Aug 5, 2014 at 17:52
  • gotcha, yeah $string['first_string'] references 'title' and 'second_string'... 'second_string' doesn't get picked up the first time around so the whole function has to start over again. Does that make sense? Commented Aug 5, 2014 at 17:53
  • 5
    Duplicate of PHP Recursion Syntax Commented Aug 5, 2014 at 18:03
  • 2
    @MikeB You just claimed that this question is a duplicate of itself... lol EDIT: Now I get it. Recursion humour Commented Aug 5, 2014 at 18:04

1 Answer 1

2

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

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

6 Comments

In this case (I've updated my $strings array above) recursion is necessary because without, $strings['first_string'] = '<b>My Program:</b> The second_string text is Hello, World! Do you like {% title %}?'... with that {% title %} at the end.
This is super clean, I love it
Sweet... that's a whole friggin' lot simpler than what I did. 'tworks. I don't know why this works... why does this work again?
@philtune If you're having a hard time grasping it, just break it down by iteration and analyze what is happening in each iteration. I've made an edit with an explanation as long as AbraCadaver approves it
Explanation by @sjagr. Thanks.
|

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.