Categories
javascript php

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

751

I have a variable in PHP, and I need its value in my JavaScript code. How can I get my variable from PHP to JavaScript?

I have code that looks like this:

<?php
$val = $myService->getValue(); // Makes an API and database call

On the same page, I have JavaScript code that needs the value of the $val variable to be passed as a parameter:

<script>
    myPlugin.start($val); // I tried this, but it didn't work
    <?php myPlugin.start($val); ?> // This didn't work either
    myPlugin.start(<?=$val?>); // This works sometimes, but sometimes it fails
</script>

2

  • 3

    Was the missing closing parenthesis in myPlugin.start(<?=$val?> intentional? Is it true that “this works sometimes”?

    – andrew

    May 20, 2014 at 14:44

  • 2

    Well this one was actually by Ben, but let’s just say that if $val is "42)" it’ll work well 😀

    May 20, 2014 at 14:45


995

+100

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>
    function reqListener () {
      console.log(this.responseText);
    }

    var oReq = new XMLHttpRequest(); // New request object
    oReq.onload = function() {
        // This is where you handle what to do with the response.
        // The actual data is found on this.responseText
        alert(this.responseText); // Will alert: 42
    };
    oReq.open("get", "get-data.php", true);
    //                               ^ Don't block the rest of the execution.
    //                                 Don't wait until the request finishes to
    //                                 continue.
    oReq.send();
</script>
<!-- snip -->

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

Some more reading material

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!

31

  • 75

    “PHP has no trivial JavaScript escape functions” — What is wrong with json_encode?

    – Quentin

    May 19, 2014 at 14:43

  • 36

    I disagree with “Highly insecure!!” and “Structured data is hard”. Encode data as JSON (JavaScript Object Notation, after all), and there you go!

    May 19, 2014 at 14:44


  • 15

    What about the significant overhead and code complexity asynchronousity introduces when making an AJAX request? When working on a JavaScript light website – making an AJAX request is tedious and not best practices.

    May 19, 2014 at 14:44

  • 8

    @BenjaminGruenbaum — JS being invalid JSON is irrelevant. I can’t think of any JSON that is invalid in JavaScript on the right hand side of an assignment.

    – Quentin

    May 19, 2014 at 14:45

  • 8

    @SecondRikudo In method 3, that example can kill the website. Example: <?php $output = '<!--<script>'; echo json_encode($output); ?>. See this question for details. Solution: Use JSON_HEX_TAG to escape < and > (requires PHP 5.3.0).

    – Pang

    May 21, 2014 at 2:23

111

I usually use data-* attributes in HTML.

<div
    class="service-container"
    data-service="<?= htmlspecialchars($myService->getValue()) ?>"
>

</div>

<script>
    $(document).ready(function() {
        $('.service-container').each(function() {
            var container = $(this);
            var service = container.data('service');

            // Var "service" now contains the value of $myService->getValue();
        });
    });
</script>

This example uses jQuery, but it can be adapted for another library or vanilla JavaScript.

You can read more about the dataset property here: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement.dataset

12

  • 3

    This answer actually seems the simplest to me for most people’s purposes. You’ve earned an upvote!

    – Eckstein

    Jul 13, 2014 at 3:39

  • 4

    I agree, not wanting to over-analyze and implement a fancy solution for a simple problem. This method separates PHP from Javascript, so that PHP still generates the HTML only, while Javascript can be external to the PHP file.

    – alds

    Jul 30, 2014 at 16:32

  • 2

    I agree this is the best option. It solves all the security issues, without the latency. You can keep JS entirely out of your HTML pages. HTML needs to be served by the application server, but JS (and CSS) does not. It’s also more semantic.

    – Ryan

    Apr 14, 2015 at 2:26

  • 1

    @Quentin You should escape ALL output, unless the output is HTML itself.

    – Hayley

    Oct 28, 2015 at 23:57

  • 2

    @asdasd — Well yes, I was just addressing the specific problem with the code in your answer rather than the general case.

    – Quentin

    Oct 28, 2015 at 23:59

100

I’m going to try a simpler answer:

Explanation of the problem

First, let’s understand the flow of events when a page is served from our server:

  • First PHP is run, it generates the HTML that is served to the client.
  • Then, the HTML is delivered to the client, after PHP is done with it, I’d like to emphasize that once the code leaves the server – PHP is done with it and can no longer access it.
  • Then, the HTML with JavaScript reaches the client, which can execute JavaScript on that HTML.

So really, the core thing to remember here is that HTTP is stateless. Once a request left the server, the server can not touch it. So, that leaves our options to:

  1. Send more requests from the client after the initial request is done.
  2. Encode what the server had to say in the initial request.

Solutions

That’s the core question you should be asking yourself is:

Am I writing a website or an application?

Websites are mainly page based, and the page load times needs to be as fast as possible (for example – Wikipedia). Web applications are more AJAX heavy and perform a lot of round trips to get the client fast information (for example – a stock dashboard).

Website

Sending more requests from the client after the initial request is done is slow as it requires more HTTP requests which have significant overhead. Moreover, it requires asynchronousity as making an AJAX request requires a handler for when it’s complete.

I would not recommend making another request unless your site is an application for getting that information from the server.

You want fast response times which have a huge impact on conversion and load times. Making Ajax requests is slow for the initial uptime in this case and unneeded.

You have two ways to tackle the issue

  • Set a cookie – cookies are headers sent in HTTP requests that both the server and client can read.
  • Encode the variable as JSON – JSON looks very close to JavaScript objects and most JSON objects are valid JavaScript variables.

Setting a cookie is really not very difficult, you just assign it a value:

setcookie("MyCookie", $value); // Sets the cookie to the value, remember, do not
                               // Set it with HTTP only to true.

Then, you can read it with JavaScript using document.cookie:

Here is a short hand rolled parser, but the answer I linked to right above this has better tested ones:

var cookies = document.cookie.split(";").
    map(function(el){ return el.split("="); }).
    reduce(function(prev,cur){ prev[cur[0]] = cur[1]; return prev },{});
alert(cookies["MyCookie"]); // Value set with PHP.

Cookies are good for a little data. This is what tracking services often do.

Once we have more data, we can encode it with JSON inside a JavaScript variable instead:

<script>
    var myServerData = <?=json_encode($value)?>; // Don't forget to sanitize
                                                 //server data
</script>

Assuming $value is json_encodeable on the PHP side (it usually is). This technique is what Stack Overflow does with its chat for example (only using .NET instead of PHP).

Application

If you’re writing an application – suddenly the initial load time isn’t always as important as the ongoing performance of the application, and it starts to pay off to load data and code separately.

My answer here explains how to load data using AJAX in JavaScript:

function callback(data){
    // What do I do with the response?
}

var httpRequest = new XMLHttpRequest;
httpRequest.onreadystatechange = function(){
    if (httpRequest.readyState === 4) { // Request is done
        if (httpRequest.status === 200) { // successfully
            callback(httpRequest.responseText); // We're calling our method
        }
    }
};
httpRequest.open('GET', "/echo/json");
httpRequest.send();

Or with jQuery:

$.get("/your/url").done(function(data){
    // What do I do with the data?
});

Now, the server just needs to contain a /your/url route/file that contains code that grabs the data and does something with it, in your case:

<?php
$val = myService->getValue(); // Makes an API and database call
header("Content-Type: application/json"); // Advise client of response type
echo json_encode($val); // Write it to the output

This way, our JavaScript file asks for the data and shows it rather than asking for code or for layout. This is cleaner and starts to pay off as the application gets higher. It’s also better separation of concerns and it allows testing the client side code without any server side technology involved which is another plus.

Postscript: You have to be very aware of XSS attack vectors when you inject anything from PHP to JavaScript. It’s very hard to escape values properly and it’s context sensitive. If you’re unsure how to deal with XSS, or unaware of it – please read this OWASP article, this one and this question.

11

  • 4

    @cHao more generally – encodings are defined as a sequence of characters and the existence of conceptual objects is a philosophical one. However, there are such things as JSON objects and they are defined by the JSON grammar. {} is a valid JSON object – see json.org

    May 20, 2014 at 3:12

  • 1

    If you’re using that definition, though, then all “JSON objects” are valid in JS.

    – cHao

    May 20, 2014 at 5:21


  • 1

    @cHao note the subtlety: JavaScript has its notion of object and JSON has its notion of object – they are not the same. When people misuse the term “JSON object” they mean a JS object, where in JavaScript land – JSON is used as a data serialization format and JSON objects appear inside strings (kind of like SQL queries in server-side languages). However, in this answer the JSON method relies on the fact that most JSON objects are also valid JavaScript object so we write a JSON object into JavaScript code.

    May 20, 2014 at 6:02


  • 1

    @cHao Ah, but I’ve foreseen this moment yesterday 🙂 stackoverflow.com/questions/23752156/…

    May 20, 2014 at 14:45

  • 2

    OK, you got me there. 🙂 It’s still safe, though; PHP’s default behavior is to escape such characters (along with other non-ASCII chars), so they never make their way into the output except as \u2028 etc. You’d have to explicitly tell it not to do that.

    – cHao

    May 20, 2014 at 15:02