Introduction

The article explains how to generate dynamic script from a backend language, such as PHP in this case. There are many reasons to choose a dynamic script over generation of JSON data that client can write script on such as 1) Restrict the client from manipulating data. 2) just provide a helper API that would just do the job. 3) Formation of feasible JS data structure is not possible.

Prerequisites

The article assumes that user knows PHP and JavaScript basics. We will be trying to read the .properties file from php, parse the configuration, understands what user wants to, prints the logic in JS and load the same in HTML to test the logic. I would also recommend you have some basic knowledge on recursive method call techniques as well. To know more on recursion, please read here.

Defining a Problem Statement

Let’s try and define the problem we are trying to solve. Consider a use-case where you have a properties file on the server and we have to use this file to show a message in the front end. Well, it is not a straightforward map of key1 to value1. Assume that, it is complex configuration of three level key to a value and each level can have wild card character ‘?’ to accept any value at that level or contain range at every level. Example: “28|71-100|?=text3″ -> if level1 value is 28 and level2 value is between 71 and 100 and level3 at any value, then the text to be used is “text3″.

Parse Properties and Generate Script

Assume that our file has one configuration per line and the first step is to understand the properties file and getting ready for generation.

$key1 = 't';
$key2 = 'w';
$key3 = 't';
function get_object_from_params($paramStr, $assignValue, $label) {
    if($paramStr == '?') {
        $paramObj = Array(
            $label => $assignValue
        );
    }
    else {
        $ranges = preg_split("/-/", $paramStr);
        if(count($ranges) == 2) {
            $paramObj = Array(
                ">" => $ranges[0],
                "<" => $ranges[1],
                $label => $assignValue
            );
        }
        else {
            $paramObj = Array(
                "==" => $ranges[0],
                $label => $assignValue
            );
        }
    }
    return $paramObj;
}
 
function parse_icon_config($txtProperties) {
    $result = array();
    $lines = preg_split("/\n/", $txtProperties);
    global $key1, $key2, $key3;
    foreach($lines as $i => $line) {
        $lineparts = preg_split("/=/", $line);
        $textvalue = $lineparts[1];
        $configparts = preg_split("/\|/", $lineparts[0]);
        if(count($configparts) == 3) {
            $windSpeed = $configparts[2];
            $temp = $configparts[1];
            $iconCode = $configparts[0];
 
            $windObj = get_object_from_params($windSpeed, $textvalue, $key3);
            $tempObj = get_object_from_params($temp, $windObj, $key2);
            $iconObj = get_object_from_params($iconCode, $tempObj, $key1);
 
            array_push($result, $iconObj);
        }
    }
 
    return $result;
}
 
$properties = file_get_contents('config/iconconfig.properties');
$propertiesObj = parse_icon_config($properties);

The above snippet parses the configuration file and generates array of config objects – one per each line. Since there is a three level key and each level parsing is almost the same, lets write a recursive method to generate the script.

function recursive_print($obj, $label) {
    global $key3;
    if(is_string($obj)) {
        return ('return \'' . $obj . '\';');
    }
 
    foreach ($obj as $key => $value) {
        if($key != '==' && $key != '>' && $key != '<') {
            $nextLabel = $key;
            $nextObj = $value;
        }
    }
    if(array_key_exists("==", $obj)) {
        return 'if(' . $label . '==' . $obj['=='] . '){' . recursive_print($nextObj, $nextLabel) . '}';
    }
    else if(array_key_exists(">", $obj) && array_key_exists("<", $obj)) {
        return 'if(' . $label . '>' . $obj['>'] . ' && '. $label .'<' . $obj['<'] . '){' . recursive_print($nextObj, $nextLabel) . '}';
    }
    else {
        return 'if(true){' . recursive_print($nextObj, $nextLabel) . '}';
    }
}
 
function get_function_text($iconCodesConfig) {
    global $key0,$key1,$key2;
    $functionCode = '';
    foreach ($iconCodesConfig as $iconConfig) {
        $functionCode .= recursive_print($iconConfig, $key0);
    }
    return 'window.getDynamicText = function('.$key0.','.$key1.','. $key2.'){' . $functionCode . 'return \'not found. some default value.\'}';
}

At each level, we analyze the data and print the appropriate conditionals in the JavaScript and then call the same method again with the next level until we reach the last level.

Our javascript generation is ready, when the PHP is requested, this is what we get:
jsgenresponse

Now, using it in our HTML is quite easy. As many other APIs out there, it loads in the window namespace and waits for us to call.

<script src="jsgen.php"></script>
....
<button ... onclick="validateAndGet()">Get Dynamic Text</button>

Here is a demo link.

demosnap

Conclusion

What did we just do: we discussed a set of use cases when we need a dynamic script rather than just data, picked up a particular scenario and worked on the same to generate a dynamic javascript using PHP and recursion techniques.