Building a Magical Golden Bridge from PHP to JavaScript with wp_localize_script()

magic golden bridge | wp_localize_script

wp_localize_script() lets you pass PHP variables to JavaScript.

One of the great reasons to love WordPress is the number of programming tasks it makes easy. Today we’ll look at perhaps my favorite bit of WordPress magic: wp_localize_script().

As the name doesn’t imply, wp_localize_script() lets you do something very important: it lets you pass PHP variables to JavaScript.

Why wp_localize_script() is Great

Before we start, it’ll be really helpful if you understand the server-side/client-side (or front-end/back-end) distinction. PHP is server-side: it does all its work before things get sent to the browser. JavaScript, in our context, is client-side: it works in your browser, to do things like hide and show elements on a mouse click.

Now: Why would we need to pass PHP variables to JavaScript? Let’s take a real-life example.

I’m writing a (bare-bones but functional) plugin that creates keyboard shortcuts for the WordPress post editing experience. With this plugin, for example, you can hit ctrl+s on your keyboard and it’ll “Save Draft” on your current post—without you needing to move your mouse up to the “Save Draft” button.

We Need PHP to Manage Site Options

Here’s the thing: I want the keyboard shortcuts to be user-configurable. If you, the user, want “Save Draft” to map to ctrl+d instead, I want that to be possible.

WordPress post editor keyboard shortcuts

This means that every shortcut binding (“ctrl+d binds to ‘Save Draft'”) needs to be saved as a site option: a piece of data to be stored in WordPress’s database, and both accessed and changed in PHP using WordPress’s useful but tangled Settings API.

We Need JavaScript to Impact the UI

For our plugin to work, we can’t just stay in PHP-land: we need JavaScript on the front end, to actually listen for the user pressing ctrl+s—or whatever custom shortcut—in a post editor page in her browser. We also need JS to take the appropriate action: trigger the page’s “Save Draft” process as if “Save Draft” itself had been clicked.

We Need Shared Variables Across Both Environments

To sum up:

  1. PHP needs to manage a site option: a server-side variable that stores the user’s custom “Save Draft” keyboard shortcut across the site.
  2. JavaScript needs to know that variable, to listen for that keyboard shortcut on the client side.

In other words, we need to be able to pass variables from PHP to JavaScript.

Hacky Ways to Pass PHP Variables to JavaScript

Hacky solutions involve manipulating the page’s markup or DOM.

There are a few ways to solve the problem we just outlined. Maybe wp-admin/post.php gets an invisible <div> in the footer, which contains a bunch of li elements that outline the currently saved keyboard bindings. Or maybe the page’s <body> tag gets a giant data-attribute="" string containing the same information, which JavaScript can read.

But WordPress gives us an elegant solution that doesn’t involve manipulating the page’s markup or document-object model (DOM). Here it is:

The Smart Way: wp_localize_script()

To understand how wp_localize_script() works, let’s look at a highly simplified version of the “Keyboard Shortcuts” plugin’s code:

Passing the Data from PHP

Here’s a simplified version of the PHP we’re using to do two related things:

  1. Enqueue the JavaScript we need, and
  2. Pass that JavaScript the data it needs.

As you read the code below, read up on WordPress hooks and enqueueing scripts and styles if you need to.

/* Environment: This is the plugin's main PHP file */

// Hook our function into WordPress's admin_init action hook
add_action( 'admin_init', 'wpshout_demo_get_scripts' );

function wpshout_demo_get_scripts() {

    // Enqueue the needed JavaScript
    wp_enqueue_script( 'wpshout_demo_update_shortcut', plugin_dir_url( __FILE__ ) . 'wpshout_demo-update-shortcut.js', array( 'jquery', 'jquery_hotkeys' ) );

    /*
    * This is an outside function.
    * It returns a PHP array of the names of site options
    * that are storing keyboard shortcut bindings
    */
    $bindingOptionsArray = wpshout_demo_return_binding_option_names();

    // Get site options to create array of currently saved bindings
    $bindingsToPass = array();
    foreach( $bindingOptionsArray as $key => $name ) {
        $bindingsToPass[] = get_option( $name );
    }

    // 'keys' will contain an array of currently saved bindings
    $dataToPass = array(
        'keys' => $bindingsToPass
    );

    /* 
    * Actual function to pass PHP to JavaScript. Args: 
    * 1. The target JavaScript file has the handle 'wpshout_demo_update_shortcut' (this is the file we just enqueued)
    * 2. The data will be called 'passedData' by the JS file
    * 3. 'passedData' will contain the data in $dataToPass
    */
    wp_localize_script( 'wpshout_demo_update_shortcut', 'passedData', $dataToPass );
}

Using the Data in JavaScript

Our actual use of the data would be too complicated to simplify, so here we’ll just create a very simple use case: we’re going to create a browser alert with the first saved binding.

/* Environment: We're in wpshout_demo-update-shortcut.js */

// Access 'keys' element of passedData object
var shortcutKeys = passedData.keys;

// Create a browser alert with the first element of passedData
alert( shortcutKeys[0] );

Again, these code snippets are both somewhat simplified. With these examples under your belt, I invite you to browse the plugin code to learn how we’re actually creating browser shortcuts in the post editor.

Commentary

You’re hopefully thinking, “wp_localize_script() is incredibly cool.” A few notes to keep in mind:

  1. You need to register and enqueue your script before passing data to it. In our case, we’re doing both things in one function—which is probably not the best for code readability.
  2. You can pass lots of stuff all at once. We’ve only got a set of 'keys' to pass, but if you needed more data you could really load up the $dataToPass associative array with lots of kinds of data.
  3. Wondering about the name? Why wp_localize_script() and not wp_send_php_vars_to_js()? Like so much in WordPress, it’s a piece of history. From the Codex: “This lets you offer properly localized translations of any strings used in your script. This is necessary because WordPress currently only offers a localization API in PHP, not directly in JavaScript… Though localization is the primary use, it can be used to make any data available to your script that you can normally only get from the server side of WordPress.”In other words, wp_localize_script()started out as an i18n thing, and turned out to be massively useful for a lot of other uses.

Now You Understand wp_localize_script()

If you’re writing code that spans the back and front end, I know you’ll love wp_localize_script(). It’ll let you stop creating invisible <div>s and whatever else, and let you pass all kinds of rich data—from your database, PHP processing, you name it—straight into JavaScript. Most simply, it’s WordPress’s way of letting you pass PHP variables to JavaScript, and that’s a very useful thing to be able to do.

Thanks for reading!

Image credit: Nelson L.


2 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Above and Beyond: Avoiding PHP Timeout and Memory Limit Errors with Ajax | WPShout
May 17, 2016 3:57 pm

[…] on knowledge of PHP, JavaScript, jQuery, Ajax in WordPress, WordPress’s hooks system, and wp_localize_script(). So it’s a bit on the advanced side. If you need to brush up on any of those topics, click […]

How To Stop a Post Publishing (Without a Featured Image) in WordPress with jQuery | WPShout
February 23, 2016 2:04 pm

[…] If there is an image in the WordPress default “Featured Image” box, #postimagediv, then $img will have a length (count of elements inside of it) greater than zero. If it is zero, then we know that there is no featured image set. That’s the first time this function exits, returning the value of passedFromServer.jsWarningHtml if so. (passedFromServer is a JavaScript global set up for the plugin by wp_localize_script in PHP, which Fred explained in an article.) […]