Efficient Way to Pass Variables from PHP to JavaScript

How do I pass variables and data from PHP to JavaScript?

There are actually several approaches to do this. Some require more overhead than others, and some are considered better than others.

In no particular order:

  1. Use AJAX to get the data you need from the server.
  2. Echo the data into the page somewhere, and use JavaScript to get the information from the DOM.
  3. Echo the data directly to JavaScript.

In this post, we'll examine each of the above methods, and see the pros and cons of each, as well as how to implement them.

1. Use AJAX to get the data you need from the server

This method is considered the best, because your server side and client side scripts are completely separate.

Pros

  • Better separation between layers - If tomorrow you stop using PHP, and want to move to a servlet, a REST API, or some other service, you don't have to change much of the JavaScript code.
  • More readable - JavaScript is JavaScript, PHP is PHP. Without mixing the two, you get more readable code on both languages.
  • Allows for asynchronous data transfer - Getting the information from PHP might be time/resources expensive. Sometimes you just don't want to wait for the information, load the page, and have the information reach whenever.
  • Data is not directly found on the markup - This means that your markup is kept clean of any additional data, and only JavaScript sees it.

Cons

  • Latency - AJAX creates an HTTP request, and HTTP requests are carried over network and have network latencies.
  • State - Data fetched via a separate HTTP request won't include any information from the HTTP request that fetched the HTML document. You may need this information (e.g., if the HTML document is generated in response to a form submission) and, if you do, will have to transfer it across somehow. If you have ruled out embedding the data in the page (which you have if you are using this technique) then that limits you to cookies/sessions which may be subject to race conditions.

Implementation Example

With AJAX, you need two pages, one is where PHP generates the output, and the second is where JavaScript gets that output:

get-data.php

/* Do some operation here, like talk to the database, the file-session
* The world beyond, limbo, the city of shimmers, and Canada.
*
* AJAX generally uses strings, but you can output JSON, HTML and XML as well.
* It all depends on the Content-type header that you send with your AJAX
* request. */

echo json_encode(42); // In the end, you need to `echo` the result.
// All data should be `json_encode`-d.

// You can `json_encode` any value in PHP, arrays, strings,
// even objects.

index.php (or whatever the actual page is named like)

<!-- snip -->
<script>
fetch("get-data.php")
.then((response) => {
if(!response.ok){ // Before parsing (i.e. decoding) the JSON data,
// check for any errors.
// In case of an error, throw.
throw new Error("Something went wrong!");
}

return response.json(); // Parse the JSON data.
})
.then((data) => {
// This is where you handle what to do with the response.
alert(data); // Will alert: 42
})
.catch((error) => {
// This is where you handle errors.
});
</script>
<!-- snip -->

The above combination of the two files will alert 42 when the file finishes loading.

Some more reading material

  • Using the Fetch API
  • How do I return the response from an asynchronous call?

2. Echo the data into the page somewhere, and use JavaScript to get the information from the DOM

This method is less preferable to AJAX, but it still has its advantages. It's still relatively separated between PHP and JavaScript in a sense that there is no PHP directly in the JavaScript.

Pros

  • Fast - DOM operations are often quick, and you can store and access a lot of data relatively quickly.

Cons

  • Potentially Unsemantic Markup - Usually, what happens is that you use some sort of <input type=hidden> to store the information, because it's easier to get the information out of inputNode.value, but doing so means that you have a meaningless element in your HTML. HTML has the <meta> element for data about the document, and HTML 5 introduces data-* attributes for data specifically for reading with JavaScript that can be associated with particular elements.
  • Dirties up the Source - Data that PHP generates is outputted directly to the HTML source, meaning that you get a bigger and less focused HTML source.
  • Harder to get structured data - Structured data will have to be valid HTML, otherwise you'll have to escape and convert strings yourself.
  • Tightly couples PHP to your data logic - Because PHP is used in presentation, you can't separate the two cleanly.

Implementation Example

With this, the idea is to create some sort of element which will not be displayed to the user, but is visible to JavaScript.

index.php

<!-- snip -->
<div id="dom-target" style="display: none;">
<?php
$output = "42"; // Again, do some operation, get the output.
echo htmlspecialchars($output); /* You have to escape because the result
will not be valid HTML otherwise. */
?>
</div>
<script>
var div = document.getElementById("dom-target");
var myData = div.textContent;
</script>
<!-- snip -->

3. Echo the data directly to JavaScript

This is probably the easiest to understand.

Pros

  • Very easily implemented - It takes very little to implement this, and understand.
  • Does not dirty source - Variables are outputted directly to JavaScript, so the DOM is not affected.

Cons

  • Tightly couples PHP to your data logic - Because PHP is used in presentation, you can't separate the two cleanly.

Implementation Example

Implementation is relatively straightforward:

<!-- snip -->
<script>
var data = <?php echo json_encode("42", JSON_HEX_TAG); ?>; // Don't forget the extra semicolon!
</script>
<!-- snip -->

Good luck!

What's the best way to pass a PHP variable to Javascript?

General Data Passing

A commonly used exchange format for JavaScript is JSON, using json_encode. A PHP file like this:

<?php
$data = array("test" => "var", "intvalue" => 1);
echo json_encode($data);
?>

then returns a JavaScript object literal like this:

{
"test" : "var",
"intvalue" : 1
}

You can directly echo it into a JavaScript variable on your page, e.g.:

var data = <?php echo json_encode($data)?>;

...or request it via Ajax (e.g. using jQuery's getJSON).

Outputting to attributes on tags

If you just need to output a string to an attribute on a tag, use htmlspecialchars. Assuming a variable:

<?php
$nifty = "I'm the nifty attribute value with both \"double\" and 'single' quotes in it.";
?>

...you can output it like this:

<div data-nifty-attr="<?php echo htmlspecialchars($nifty)?>">...</div>

...or if you use short tags:

<div data-nifty-attr="<?= htmlspecialchars($nifty)?>">...</div>

Efficient way to Pass variables from PHP to JavaScript

If you don't want to use PHP to generate your javascript (and don't mind the extra call to your webserver), use AJAX to fetch the data.

If you do want to use PHP, always encode with json_encode before outputting.

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

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

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.

How to pass variables from PHP to Javascript

In my opinion, the best way to pass many variables from PHP to Javascript is to collect them in a PHP object, convert the object to JSON and print it out in a script tag on your website.

In your controller:

$config = new stdClass();
$config->site_url = site_url('manage/getSerials');
$config->user_name = 'David';

...pass the $config var somehow to your view.

In your view:

<script type="text/javascript">
var MyConfig = <?= json_encode($config); ?> // global var "MyConfig"
</script>

It will generate this code:

<script type="text/javascript">
var MyConfig = {
site_url: "what/your/function/returned",
user_name: "David"
}
</script>

And finally access your vars like this in your Javascript files:

console.log(MyConfig.site_url)

The global Javascript var MyConfig has the additional benefit of having all your dynamic variables namespaced in a Javascript object.

how to pass variable from php template to javascript

The first way is definitely the least complicated and fastest.

The second one adds an additional processing step (the parseJSON()) that isn't necessary.

The third way is good if you're dealing with lots of data that is optional (i.e. is needed only if the user requests it, and it isn't 100% sure whether that will happen) or dynamic. It creates a new request though, and is not going to be immediately available.

If you don't want to use globals, you could e.g. wrap your JavaScript functions into an object, and populate an object property from PHP:

<script>
MyObject.MAP_POINTS = <?php echo json_encode($this->points); ?>;
</script>


Related Topics



Leave a reply



Submit