A while back, I wrote a post detailing why it was a bad idea to generate Javascripts using PHP in WordPress plugins. In that post, I mentioned a couple of better ways to do it.

At the time, I didn’t know about the third, and best way, to accomplish this. Mike’s comment over there reminded me of it. WordPress has it built in.

If you already know about wp_localize_script, you can stop reading now.

The wp_localize_script function was made in order to allow for WordPress translations to be able to also translate some of the JS files inside WordPress. Thus the name “localize”. The way it works is to load up the translated versions of text from the translation files and then include them into the resulting HTML output as a Javascript object. The scripts then use that object to produce any text output they need to produce.

Turns out that’s really similar to our goal of sending arbitrary parameters from WordPress to be used by Javascript code.

How to do it:

1. Make your script static (instead of generated) and enqueue your script as per normal. Example:

wp_enqueue_script('my-script','/path/to/whatever.js',…);

No real changes there. You’ll have to come back and modify your script to use these parameters it’s getting passed, but we’ll get to that in a minute.

2. Build an array of your parameters that you want to send to the script.

$params = array(
  'foo' => 'bar',
  'setting' => 123,
);

Note that my parameters are simple examples, but this is PHP code. You can get your parameters however you like. Such as get_option to pull them from the database, perhaps.

3. Call wp_localize_script and give your parameters a unique name.

wp_localize_script( 'my-script', 'MyScriptParams', $params );

What this will do is make WordPress output an inline script with your parameters (properly encoded) just before the enqueue outputs the script tag that loads your script in the first place. So then those parameters will be available to your script as an instance of an object with “MyScriptParams” (from my example).

This means that Javascript code can now reference them as attributes of the name you gave.

So, step 4. Modify your script to use those parameters. In my example, I used “MyScriptParams” and the parameter names are “foo” and “setting”. In my Javascript code I can use them as “MyScriptParams.foo” and “MyScriptParams.setting”.

Much cleaner. One static and unchanging JS file to cache. Parameters get put into your HTML itself as a one-liner. You can deal with the parameters using a normal PHP array before passing them over. No need to screw around with generating Javascript from PHP or looking for wp-load or even messing with tricky actions.

Perfect.

Shortlink:

28 Comments

  1. […] Note: There is a followup post to this one, which details an even better way than the two given below: http://ottopress.com/2010/passing-parameters-from-php-to-javascripts-in-plugins/ […]

  2. […] Passing parameters from PHP to Javascripts in plugins » Otto on WordPress. Share and […]

  3. Otto,

    Thanks for pointing me this direction. Unfortunately, after spending the day coding the construction of two arrays that are three levels deep, I have discovered “wp_localize_script only supports arrays with one level for translation purposes.” Is there an alternative that would allow me to pass these complex arrays via wp_localize_script or something similar?

    • If you’re needing to pass extremely complex structures, you should hook to wp_head and output your own script tags and variables. You can use json_encode() to convert complex PHP structures into Javascript capable structures.

  4. Hi Otto,

    I think I may have found the one case where including wp-load.php is necessary. Hopefully I’m wrong because I hate it and don’t want to include it. I’m making a plugin that needs to use a rest api to retrieve files and everything needs to be OAuth signed, etc. I want to pull files from this service and throw them at the browser to display them. So at the top of my plugin I have this horrible thing:

    if (isset($_GET['display'])) {
    require_once( "../../../wp-load.php" );
    require_once( plugin_dir_path( __FILE__ ) . "/includes/connection.php");

    $connection = new Connection(
    get_option( 'consumer_key' ),
    get_option( 'consumer_secret' ),
    get_option( 'access_token' ),
    get_option( 'access_token_secret' ));

    $metadata = json_decode($connection->get( $_GET['display'] ));

    header("Content-Type: " . $metadata->{ 'mime_type' });
    echo $connection->get( $_GET['display'],null,true);

    exit;
    }

    Now I need those keys and access tokens for OAuth. I can’t put them in a file and read them because they need to be secret, I can’t bake them on a script or url on a page since they need to be secret. The plugin puts them into the database using the standard options calls. So I need to have PHP look these values up somehow so we can sign our API request for OAuth. And that’s where I’m stuck. I have no guarantees for any access to a database other than through the WordPress API.

    Sorry for so much spam but it’s really bugging me and I’m hoping you will be able to see something blindingly obvious I’m missing to not have to includ wp_load!

    Many thanks!

  5. […] variable to JavaScript for your WordPress plugin, go through this very good post by Otto – Passing parameters from PHP to Javascripts in plugins This is a very safe and straightforward way to pass your PHP variables into your JavaScript.  This […]

  6. Hi Otto,

    Great article, it surely put me in the right direction for what i’m looking for. I hope you have an anwers to the question remaining:

    in trying to pass data as shown above, all is well!
    im now trying to pass data from a widget to the array. Problem is that all data put into the widget option is a multidimensional array, where the data set is depending on the instance of the widget (allways multiwidget). ie the title of a widget is inside [2][title] or [3][title]. how can i pull the right data?

    • Pull the data out of the multidimensional array and put it into a regular one dimensional array. Then send it to the script. JS can’t cope with multidimensional arrays. Simplify your data before sending it to the script.

  7. Great solution! 🙂 I found another way ( on inchoo.net) to passing parameters… for example creating javascript file in php with “content-type: application/x-javascript”… but i think will use wp_localize_script (it was created for translate javascript content?)
    thanks for share!

  8. I have a error from the console when trying to do this : “php_params is not defined” in the /js/script.js file.

    i don’t what i did wrong

    // inside functions.php
    wp_enqueue_script(‘myscript’, get_stylesheet_directory_uri().’/js/script.js’, array(‘jquery’));

    // inside single.php
    ”,
    1 => ”,
    2 => ”
    );

    wp_enqueue_script(‘myscript’);
    wp_localize_script(‘myscript’, ‘php_params’, $params);
    ?>

    // and inside /js/script.js
    alert(php_params);

  9. sorry i forgot to put the markup in the previous message. here it is again :

    I have a error from the console when trying to do this : “php_params is not defined” in the /js/script.js file.

    i don’t what i did wrong

    // inside functions.php
    wp_enqueue_script(‘myscript’, get_stylesheet_directory_uri().’/js/script.js’, array(‘jquery’));

    // inside single.php
    $params = array(
    0 => '',
    1 => '',
    2 => ''
    );

    wp_enqueue_script('myscript');
    wp_localize_script('myscript', 'php_params', $params);

    // and inside /js/script.js
    alert(php_params);

    • Ok it’s necessary that the array declaration and the wp_localize_script stay before wp_head() (so inside single.php, it has to be before the header.php call. )

      now it’s working.

  10. I’m making a widget and I need to send parameters from the widget code to javascript file… I put the wp_enqueue_script code line before the class code and wp_localize script in a function from the class, beacuse that where i get the paramaters from the instance, but It doesn’t send the parameters.. I must be doing something wrong… where should I put wp_enqueue_script and wp_localize_script?

  11. If only something similar could be done for css…

  12. Is there a way to preserve boolean values with wp_localize_script?

  13. Very nice man. Thanks!

  14. Hi All,
    I am trying to use jqgrid in a plugin. jqgrid relies on the parameter url:’external.php’ file.

    I can not think any other way than ussing wp-load.php to allow the external.php file access the wpdb functions.

    Does anyone knows how to implement jqgrid without using wp-load.php….any sample much appreciated.
    Thanks.

    • jqgrid doesn’t rely on having an external PHP file, it relies on having a URL to talk to in order to get the data. So you give it the URL to the admin-ajax.php file, along with a query parameter, which you catch in your plugin and use to trigger the proper output.

  15. […] variable to JavaScript for your WordPress plugin, go through this very good post by Otto – Passing parameters from PHP to Javascripts in plugins This is a very safe and straightforward way to pass your PHP variables into your […]

  16. This is rad, can’t believe I just stumbled across it. Only question is, would not be able to minify scripts correct? As whatever parameters got passed in would not match the jumbled up minified version?

    I am wanting to use this option to add a few options to the customizer for a homepage slider; speed, transition etc. And then pass those into a function to power flexslider…

  17. I am missing something in this example. How does the javascript function get called?

  18. Sorry if it’s an outdatet post, but I don’t find a solution to my problem related to wp_localize_script, maybe someone has a solution. The problem is when I try to put more than one in the same page, for now I implemented it this way:

    PHP
    $example_arr = array( ‘example_id’ => ’123′ );
    wp_localize_script( ‘example_handle’, ‘example_obj’, $example_arr );

    JS
    var id = example_obj.example_id;

    this works well, for example I can use it in a shortcode like this:
    [example id=”123″]

    but if I try to put more than one in the same page:
    [example id=”123″]
    [example id=”456″]

    only the last id is rendered, this is because ‘example_obj’ gets the last value of example_id

    I tried to add an ID to ‘example_obj’ something like this: ‘example_obj’.$id
    but I don’t know how to get it in JS, for example if I created 2 objects:

    ‘example_obj123′ and ‘example_obj456′, how can I get these in my JS?

    thanks in advance

  19. There is actually a better way than any outlined above. Store the required variables in semantic html elements within the page or within a data attribute.

    Then just access the variables via static javascript.

    The variables can be passed to the page through one of the wp hooks. This approach is best as the js it allows true separation of logic and content, keep the js unobtrusive, and allows it to be cached.

    • The wp_localize_script method does exactly that. It takes your PHP variables and creates a bit of javascript in the page containing those variables, which other static javascript code can then reference.

      • no it’s different. Wp_localize_script creates inline javascript (which sucks).

        using my approach the JavaScript stays as a seperate file (which wordpress does not touch). That javascript file when executed pulls the variables it needs from the DOM.

  20. Hi,

    A lot of thanks for the tutorial. For any reason, I can´t use variables to build de $param array. It works with static value, but when i try to use a variable to get dynamic values, it doesn´t work. Even with a simple $variable = 1 , $variable2 = 2, it doesn´t work. Do you know what can be wrong in my code?

    $params = array(
    ‘foo’ => $variable,
    ‘setting’ => $variable2,
    );

    A lot of thanks,

    Victor

Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Need to post PHP code? Wrap it in [php] and [/php] tags.