Most efficient way to pass PHP variables to external JavaScript (or jQuery) file
Asked Answered
M

2

5

I've read several posts about the question and found this to be the simplest solution, here is my code:

js inside PHP code

<script>
    <!--// 
      var jsBaseurl = <?php echo json_encode(BASE_URL."/"); ?>;
      var jsTitle = <?php echo json_encode($h1_title); ?>;
      var jsSubtl = <?php echo json_encode($h2_title);?>;
    //-->
</script>
<script src="external.js"></script>

and the external.js

var siteURL=jsBaseurl;
alert(siteURL+jsTitle+jsSubtl)

it works fine, my question is regarding to the following comments by Pang and biplav:

WARNING: This can kill your website. Example:

<?php $myVarValue = '<!--<script>'; ?>

See this question for details. Solution: Use JSON_HEX_TAG to escape < and > (requires PHP 5.3.0). - Pang

Another downside of this is that impacts the inital page load time. - biplav

I would like to know a simple solution for Pang's comment and how this all impacts the performance (page load time). Thanks a lot!

Mylesmylitta answered 20/7, 2014 at 21:43 Comment(9)
It would kill your website if the output if json_encode() contains an illegal character in JavaScript which is not very likely.Aleph
It doesn't affect page performance if you're using PHP in anycase and as long as you don't put stupid things in your own PHP it won't break but if you put stupid things in any PHP script you can kill your own website. You are the webmaster!Kirman
@Daniel which would mean that the json_encode() is broken and outputs illegal JSON, because there is no legal JSON that would be illegal JavaScript.Marque
Since json_encode() really produces a String, I'm not sure how this applies to being a problem, more than the user having Firebug.Milium
@Marque Was not 100% sure about that but thank for clarifying ;)Aleph
@Marque var jsTitle = <?php echo json_encode($h1_title."<!--<script>"); ?>; kills the output, tested.Mylesmylitta
@Mylesmylitta This value was not in the question when I was commenting and the only value I thought might kill the output was "</script>" but I didn't test it. Actually I'm surprised that "<!--<script>" does the trick - I thought everything until </script> would be ignored by the html parser. But I guess I was wrong, I'll have to look into it in more detail. Thanks for pointing it out to me. By the way, it's been like a decade since I last saw html comments inside script blocks. :) Kudos for the poster for thinking about Netscape 1.0 compatibility :)Marque
@Marque I agree :) ... this is an almost impossible scenario, but meanwhile we all agreed json_encode will prevent any issue, Pang just came up with this example to defend his comment. And he was right.Mylesmylitta
Just wanted to point out this excellent Q & A mentioned by @Pang regarding my question, How to pass variables and data from PHP to JavaScript?Mylesmylitta
H
9

About question 1: use JSON_HEX_TAG in json_encode()

  • Example 1
    Consider this simple piece of code.

    <script>
        <?php $myVarValue = 'hello world'; ?>
        var myvar = <?php echo json_encode($myVarValue); ?>;
        alert(myvar);
    </script>
    

    Output:

    <script>
        var myvar = "hello world";
        alert(myvar);
    </script>
    

    It alerts hello world. Good.

  • Example 2
    Let's try having </script> as the string.

    <script>
        <?php $myVarValue = '</script>'; ?>
        var myvar = <?php echo json_encode($myVarValue); ?>;
        alert(myvar);
    </script>
    

    Output:

    <script>
        var myvar = "<\/script>";
        alert(myvar);
    </script>
    

    It alerts </script>. Good.

    As you can see, the slash (/) is correctly escaped as \/,

  • Example 3
    Now, consider this very special string: <!--<script>

    <script>
        <?php $myVarValue = '<!--<script>'; ?>
        var myvar = <?php echo json_encode($myVarValue); ?>;
        alert(myvar);
    </script>
    

    Output:

    <script>
        var myvar = "<!--<script>";
        alert(myvar);
    </script>
    

    Surprisingly, it does not alert anything, and there's nothing in the error console. What?!

    If you check JSON's spec, none of the characters in <!--<script> need to be escaped, so what went wrong?

    JSON string

    Image adapted from json.org

For a complete and well explained answer, read this amazing Q & A. In short, it turns out that having <!--<script> in a <script> block confuses the HTML parser. PHP actually did its job correctly in json_encode(); you just can't have a <!--<script> there, even though it is a perfectly valid JavaScript string!

I did a few simple tests myself. The browsers actually ignore everything after <!--<script>, so if it happens in the middle of a page, the entire second half of the page is gone! I'm not sure if someone can actually inject something malicious there to, say, execute arbitrary code, but that's bad enough.

Also,

  • If you have not just a string in $myVarValue, but a complex object like array("key" => array("one", "and<!--<script>two", 3)), which includes <!--<script>, it's still bad.
  • If you have a plain HTML file (i.e. no PHP) and you have <!--<script> anywhere (even in a JavaScript comment) in your <script> block, it's also bad.
  • If you are using other, non-PHP, server-side programming languages, and produced <!--<script>, it's bad too.
  • If your PHP is outputting JavaScript directly (Content-type: application/javascript), it's actually ok [1].

The solution? Use JSON_HEX_TAG to escape < and > (requires PHP 5.3.0).

<script>
    <?php $myVarValue = '<!--<script>'; ?>
    var myvar = <?php echo json_encode($myVarValue, JSON_HEX_TAG); ?>;
    //                                            ^^^^^^^^^^^^^^
    alert(myvar);
</script>

Output:

<script>
    var myvar = "\u003C!--\u003Cscript\u003E";
    alert(myvar);
</script>

It alerts <!--<script>. Hurray!

It works because there's no more <!--<script> in the output, so no more HTML parsing problems.

Note: you don't need JSON_HEX_TAG if you're not printing into a <script> block.

[1] Here, "ok" merely means it is free from the <!--<script> issue. Dynamically generating external JavaScript files is not recommended as it has tons of disadvantages, such as those stated here, here, here.


About question 2: initial page load time

Actually, it's rather obvious. If the time needed to obtain the value of $myVarValue is long (e.g. you're fetching lots of data from DB), PHP will have to wait, so is the browser, and the user. That means longer initial page load time. If you load the data later with Ajax instead, they won't have to wait to see the initial result, but then, the Ajax call would be an extra HTTP request, so it means more workload to the server, and more load to the network.

Of course, each method has its pros and cons, so you have to decide. I suggest reading this excellent Q & A.

Hutchinson answered 26/7, 2014 at 11:9 Comment(1)
@Pang, many thanks for the time and detailed example! Since most people were unaware of this possibility, I hope it also help others searching to pass PHP variable into external .js file. I think the <!--<script> scenario is very common so the concern is real.Mylesmylitta
D
-1

Pretty sure that won't break it. The whole point of json_encode is that it's safe to dump.

</script> might break it, but PHP escapes / as \/ by default so you shouldn't have to worry about it.

Daynadays answered 20/7, 2014 at 21:47 Comment(2)
Niet, Yatko, Can you please test this below? This doesn't alert anything unless I modify the string literal. Maybe it's just my bad luck, but I tested this on different browsers, and even tested running this on 2 different online PHP "fiddlers". Thanks a lot. <script> <?php $myVarValue = '<!--<script>'; ?> var myvar = <?php echo json_encode($myVarValue); ?>; alert(myvar); </script>Hutchinson
Pang is right, it does break the code: var jsTitle = <?php echo json_encode($h1_title."<!--<script>"); ?>; - @Pang, could you please explain your suggestion regarding the JSON_HEX_TAG. Thank you!Mylesmylitta

© 2022 - 2024 — McMap. All rights reserved.