Originally published here: http://ottodestruct.com/blog/2010/dont-include-wp-load-please/

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/

Time for Otto’s general griping: WordPress plugin programming edition.

Here’s a practice I see in plugins far too often:

  1. Plugin.php file adds something like this to the wp_head:
    <script src='http://example.com/wp-content/plugins/my-plugin/script.js.php'>
  2. Script.js.php has code like the following:
    <?php
    include "../../../wp-load.php";
    ?>
    ... javascript code ...
    

The reason for this sort of thing is that there’s some option or code or something that the javascript needs from the database or from WordPress or whatever. This PHP file is, basically, generating the javascript on the fly.

Usually, the case for this turns out to be something minor. The code needs the value from an option, or some flag to turn it on or off. Or whatever.

Problem is that finding wp-load.php can be a bit of a chore. I’ve seen extreme efforts to find and load that file in plugins before, including searching for it, examining the directory structure to make decent guesses, etc. This sort of thing has existed even before wp-load.php came around, with people trying to load wp-config.php themselves and such.

But the real problem is simpler: This is always the wrong way to do it.

Why this is wrong

  1. You don’t have the first clue where wp-load.php actually is. Both the plugin directory and the wp-content directory can be moved around in the installation. ALL the WordPress files could be moved about in this manner, are you going to search around for them?
  2. You’ve instantly doubled the load on that server. WordPress and the PHP processing of it all now have to get loaded twice for every page load. Once to produce the page, and then again to produce your generated javascript.
  3. You’re generating javascript on the fly. That’s simply crap for caching and speed and such.

The right way? Well, there’s two options.

Right Way the First

Generate your options separately, put them in using wp_print_scripts.

Examine this pseudo-code:

add_action('wp_print_scripts','myscript');
function myscript() {
?>
<script type="text/javascript">
  var plugin_option= <?php echo json_encode(get_option('plugin_option')); ?>;
</script>
<?php
}
wp_enqueue_script('myscript','...myscript.js',...);

Basically, the plugin option value is inserted directly into the page. The myscript.js file that loads shortly afterwards can use this value however it likes.

Why this is better:

  1. No searching for wp-load.php.
  2. The javascript is static, only your options are variable. No added load on the site.
  3. Static scripts mean you get great speed from caching.

Sidenote: Note the use of json_encode? You should always use this when producing javascript variables from PHP variables. It handles quoting and escaping and everything for you. It can even turn PHP arrays into javascript arrays nicely! Handy for storing all your options in one place.

What if you have a ton of plugin options though? What if you really WANT to generate that javascript on-the-fly?

Right Way the Second

Generate the javascript from a call to WordPress itself, not to a separate file.

Examine this pseudo-code:

add_filter('query_vars','plugin_add_trigger');
function plugin_add_trigger($vars) {
    $vars[] = 'plugin_trigger';
    return $vars;
}

add_action('template_redirect', 'plugin_trigger_check');
function plugin_trigger_check() {
	if(intval(get_query_var('plugin_trigger')) == 1) {
	?>
function javascript_code() {
...
}
<?php
	exit;
	}
}

That code does something a little clever. Basically it’s adding a new query variable to be used as the “trigger”. When the trigger gets pulled, a bunch of javascript is generated, then the code *exits*, stopping WordPress from proceeding any further.

So, with that code in a plugin, a call to http://example.com/?plugin_trigger=1 will now produce your javascript code. This is running entirely within the content of a WordPress call, so you get all the WP functions and database access with which you can generate your code as well.

Thus, you can happily put your

<script src="http://example.com/?plugin_trigger=1">

code into the page and it’ll load up that “file” just fine.

Why this is better:

  1. No searching for load.php
  2. … Well, okay, there is no other reason. The load problem still exists, and your caching issues still exist. You’re programmatically generating code here, after all. It’s not a particularly good practice to do. Still, sometimes this is easier and faster to develop, even if it’s never actually “necessary”.

Also see that while I’m using the number 1 there as the value I’m checking for, that value can be anything you like. If you want to be a smartass about it and have all sorts of different things that could be generated, you can do them all with that one trigger. It’s still a generally bad idea because of the added load, but hey, maybe you have a legitimate reason. I’ve seen one or two valid reasons to do this before.

Wrap up

Also note all of the above also applies to “generating” CSS code. It’s just as unnecessary. Usually more so.

So please, stop including wp-load. It’s just wrong. Let WordPress load itself, and make your plugin do the output it needs to produce in the right places.

Shortlink:

42 Comments

  1. [...] include wp-load, please. Edit: This post has moved to here: http://ottopress.com/2010/dont-include-wp-load-please/. Take your comments [...]

  2. Hey Otto, I’ve come with a idea that may help in a lot of cases.

    It’s for when we wanna build a dynamic CSS or JS, and during the page building we already know the data we wanna use. Generally that happens when the CSS/JS just needs to use a get_option() to load some data from database, which we can access in page-loading time, or when in page-loading time we generate something we wanna pass to it.

    Anyway, if before we add the or potentially print the whole code in HTML document, we already know the info that code will need, we can pass it as GET parameters to the file. In the href attribute, after the file URL, we add a ‘?’ and just pass our data as key=value, as we normally do when we manually build a GET parameters string, using urlencode () and so forth.

    Then, when the dynamic CSS/JS is loaded, we just use $_GET[] to get those data back and deal with default values when a parameter is not present. I’ve tested it with CSS for a plugin I’m developing and it worked beautifully, in admin page I allow user to set config parameters and when the file must me used I pass them as GET parameters.

    For values that are arrays, what I’ve thought is use serialize() and unserialize(), but didn’t use in practice.

    And there’s another issue, if we use wp_enqueue_style(), we can pass our prepared string to it as if it was the file version, and WordPress appends our string, but before it appends a “?ver=”, which would turn our first parameter key to the “ver” parameter value, and break this first parameter. In this case, I just start the string with “0=dunny”, which results in “ver=0=dummy&firstparameter=…”, works great!

    I believe this solution can solve most cases where wp-load is required only to read data, any idea on how to enhance it would be very appretiated :D

    In a few weeks I’m gonna publish my plugin, then you can see it working in practice.

    • Your solution still requires a second, and wholly unnecessary, round trip to the server just to produce your code.

      It’s really a lot better to insert the code into the page directly. It’s faster and it requires less server hits.

      • Yeah, as any js and css does :P

        Beyond all advantages of separating HTML, JavaScript and CSS, all this is to “access” WordPress when dynamically generating these files. And it doesn’t require the use of wp-load, which is much faster already.

  3. Hello Otto,
    nice post – a ask, do you have an example on a sorce-file for real work example. I dont understand your tutorial not perfectly. Thanks for reply.

    • It’s hard to give an example without knowing exactly what it is that you’re trying to accomplish, basically. There’s a lot of ways to do it, but including wp-load from a plugin is always the wrong way.

  4. Thanks for you reply!
    I will include a own javascript-file. In this js-file it is important to use the path of WP, get_options(‘wpurl’) as example and i will not use the wp-load.php in this js.file, as php-file and send header as javascript. YOu has examples of code hier, but this are foo examples and i will read this on a plugin or script for WP, on a real example. Maybe i understand your solution better. Thanks for read my bad english and also thanks for your time.

    • Okay, so if there’s only some small piece of information you need, then really, what you should do is to include that information onto the main HTML of the page itself as a javascript variable, then have your script use that variable when it gets included.

      “Right Way the First” above basically demonstrates exactly how to do this in a plugin.

      In other words, you’re basically saying that you want to make a PHP file which generates javascript code. That’s a BAD way to do things. Instead, make the javascript code static, such that it doesn’t have to be generated but can merely be loaded directly. The pieces that you would have needed to generate before, rewrite them to use variable names. Then have code in your plugin that sets those variables on your main site itself.

      Does that help?

      • Yes, i think so and i have an idea for my work.
        I will give the the path on a variable for the javascript and use this on my js. The js i will include with wp_enqueue_script().
        Many thanks, i will test this and the change all my sources with wp-load.php.

        I have read in so much plugins and all go the way via hook wp_head or wirte the source via echo in the pages. Small one of plugins use wp_enqueue_script() – i think the right way, and i hove no find a plugin without wp-load.php for values from WP, example the path. I think, it is important, that more people write plugins and posts for dont use wp-load.php.

  5. [...] over to Otto’s blog and read his post entitled don’t include wp-load, please which I’m in complete and total agreement with. I’d like to add to the solutions with [...]

  6. Hi Otto,

    (here is it reformatted)

    Nice post, thanks.

    Question though: @Ozh mentioned in comments on your other site to use URL parameters to which you said “this still causes caching problems.” In looking at it it doesn’t seem to be the case so I’m asking to see what I am missing. (I’m assuming that the generated Javascript is a function of the URL parameters and nothing more.) Let me give a simply example to allow us something to discuss:

    script.js.php?foo=1&bar=2

    if script.js.php contains the following (which is mindlessly simplistic on purpose to allow us to discuss):

    <?php
    // script.js.php
    var test = json_encode(array(
    ‘foo’ => $_GET['foo'],
    ‘bar’ => $_GET['bar'],
    ));
    ?>

    Doesn’t every permutation of ‘foo’ and ‘bar’ cache correctly; i.e. for any given URL you will always get exactly the same Javascript, no?

    Or were you referring to the fact that is we have 10 different ‘foo’s and 10 different ‘bar’s we could end up with 100 different URLs each of which would need to be downloaded and cached separately?

    If I am not missing something it would seem then that using URL parameters would not be so much a “caching problem” but instead a working solution that is poorly optimized for HTTP caching, correct? (Note the following script would cause a what I would term to be a “caching problem.”)

    <?php
    // script.js.php
    var test = time();
    ?>

    Again, I’m just trying to see if I am missing anything. Thanks in advance.

    -Mike

    • There’s a few problems with it.
      1. Sometimes browsers don’t like to cache things with ?foo=bar and such in them. Not every browser is Firefox or Chrome.
      2. As you stated, if you have a lot of possible inputs, then you’ll have a lot of possible resulting scripts. This is a problem considering that we’re talking about caching by individual browsers here.

      Basically, creating GET parameters like that make things not work as well or as beautifully and they should be avoided. Sometimes they’re acceptable when you’re in a hurry or just don’t really care, but ideally I prefer my code to be more elegant.

      BTW, if you’re using wp_enqueue_script for this sort of thing, WordPress has a function designed to do this the right way called wp_localize_script. It was originally designed for extending I18N translations into javascript files, but it works equally well for parameter passing to static JS files. It’s definitely the preferred way to go when the alternative is having PHP code that dynamically builds Javascript code…

      To use it, you just enqueue your STATIC javascript as per normal:

      wp_enqueue_script(‘whatever’,'/path/to/whatever.js’,…);

      Then you call localize script with an array of your parameters:

      $myparams = array(‘foo’=>’bar’, ‘setting’=>123);
      wp_localize_script(‘whatever’,'ParamName’, $myparams);

      What this will do is make WordPress output an inline script with your parameters (properly json encoded) just before the output of the script tag to load your javascript. Then those parameters will be available to your javascript as an instance of an object with “ParamName” (from my example). So your static script can reference them as “ParamName.foo” and “ParamName.setting” and so forth.

      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… Perfect, basically.

  7. [...] 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 [...]

  8. Otto, you rock it!!! i thoght same about wp_head and i came here searching for a solution with a plugin that uses this and once you use a child theme it break code…. solved and thanks!

  9. I’ve been using the Right Way the Second for quite awhile to build replies to front end AJAX requests. (Thanks!) I build my version of http://example.com/?plugin_trigger=1 like this:

    $ajax_url = bloginfo( 'url' ) . '?plugin_trigger=1';

    That’s been working for nearly everyone, but I have one report from someone with a server configuration that requires PATHINFO permalinks reporting that it won’t work without adding index.php before the querystring. Is there a more generic “template redirect URL” I should be using?

    • There’s easier ways to do javascript requests back to the server. Relevant codex article: http://codex.wordpress.org/AJAX_in_Plugins#Ajax_on_the_Viewer-Facing_Side

      I’ll give you an example of how I recently did this to get a random image from image galleries (this is actually implemented on http://ma.tt, it’s the random photo in the sidebar).

      In the theme’s functions.php file, I used code similar to this:


      add_action('wp_ajax_nopriv_randimage', 'themename_random_image');
      function themename_random_image() {
      // does some SQL trickery to get a random photo
      $id = themename_get_random_photo_id();

      // get the photo's custom sized thumbnail
      $image = wp_get_attachment_image_src($id, 'themename-random-thumbnail', false);
      list($src, $width, $height) = $image;

      // get the link to the full photo
      $url = get_permalink( $id );

      // build the return array
      $ret['url'] = $url;
      $ret['src'] = $src;

      // sanitize the callback function name
      $callback = preg_replace('/[^a-zA-Z0-9]/', '', $_GET['callback']);

      // set the header
      header( 'Content-Type: application/javascript' );

      // return the json data and exit
      echo $callback.'('.json_encode($ret).')';
      exit;
      }

      That code basically gets a random photo and returns a JSONP style object with the URL of a thumbnail and the URL of the link to the photo.

      Then, in the actual sidebar code, I have something similar to this:

      <div style="width:187px; height: 124px;" class="randsidebar">
      <a href="">
      <img src="< ?php bloginfo('template_url'); ?>/images/frame1.png" width="196" height="141" />
      </a>
      </div>
      <script type="text/javascript">
      var data = {
      action: 'randimage'
      };
      jQuery.getJSON('<?php echo admin_url('admin-ajax.php'); ?>?callback=?', data, function(response) {
      jQuery('.randsidebar').css("background-image", "url("+response.src+")");
      jQuery('.randsidebar a').attr("href", response.url);
      });
      </script>

      That uses jQuery to go and retrieve a random image from the page. The result comes back as a JSONP callback, which gets passed into that function as the “response”. The jQuery code there then takes that response and changes that DIV to have the image as the background, and changes the link on top of it to link to the image. The “frame1.png” is a transparent png file that makes the nice frame around the image. The frame sits inside the div, and since the div gets the image as the background, the frame overlays the background image, thus producing the framed effect.

      The key to all this is the “admin-ajax.php” file. That filter I defined before called “wp_ajax_nopriv_randimage” gets called because my “action” is “randimage”. Thus the handler for the randimage action is automatically called, without having to check variables or anything else.

      • That’s a generous reply, thanks again! It’s nice to see what you chose to put in a real life implementation.

        I implemented my AJAX handler in WP 2.8, and still had 2.7 installs, but you’ve convinced me to start using wp_ajax_nopriv now.

        It’s interesting to me that you chose to use JSONP, even though you could have done straight JSON in this scenario, right?

  10. [...] B ] : “Right way the second” as defined here : http://ottopress.com/2010/dont-include-wp-load-please/. This is not a great alternative, but it will work if you’re a stickler for using separated [...]

  11. Hi Otto-

    Nice write-up, and you are correct that the way you outline is much nicer and cleaner than loading the whole system. However this doesn’t take into account more robust situations…

    What if when I generate a js/css file I need to pull 10 different things, query the database, etc? Is this the case where loading in wp-load is ‘acceptable’ or is there another method that is preferable?

    Thanks,

    Kevin

    • Well, mainly, there’s almost never a good reason to actually do that.

      Javascript can use variables in the main page and have the actual code itself be static and unchanging (See http://ottopress.com/2010/passing-parameters-from-php-to-javascripts-in-plugins/ for an example).

      CSS is additive. The few variable items (and they should be few) can be put into a separate file or call. If you really want to allow CSS input, you can use the second method given in the post above, or you can just hook to the init action and notice a custom $_POST variable to make it output the CSS. This isn’t the best way as it still requires another hit to the site, but it does mean that you don’t have to find and try to load WordPress manually, since you can just load WordPress normally then change the output to what you want it to be. It’s lighter-weight to do that than to include wp-load.

  12. I apologize for posting on an older thread, but I am facing a dilemma and would welcome your thoughts on best approach. I need to generate a couple of JavaScript arrays from my database as well as a set of functions that are based on the contents of those arrays. The total script length is such that I don’t want to incur this overhead on every page. Is it possible to dynamically generate a then-static *.js file when the plugin is first activated and subsequently regenerate the file when the user changes the plugin options? I have Googled for information on this approach without success, so perhaps such a thing is not possible or is regarded as bad practice for some reason. What are your thoughts?

  13. [...] watch out!” says that core dev. The WP Honey Badger is just cuh-razy, including wp-load.php all over the place. It has no regard for how heavy the page is getting from loading WordPress over and over again. [...]

  14. [...] B ] : “Right way the second” as defined here : http://ottopress.com/2010/dont-include-wp-load-please/. This is not a great alternative, but it will work if you’re a stickler for using separated [...]

  15. [...] solutions in loading the wp-load.php and therefore access to all features of WordPress. Long ago Otto (Samuel Wood) already referred to this fact and this articles shows solutions. Questions still there and still [...]

  16. [...] solutions in loading the wp-load.php and therefore access to all features of WordPress. Long ago Otto (Samuel Wood) already referred to this fact and this articles shows solutions. Questions still there and still [...]

  17. [...] solutions in loading the wp-load.php and therefore access to all features of WordPress. Long ago Otto (Samuel Wood) already referred to this fact and this articles shows solutions. Questions still there and still [...]

  18. Hi, 2 years later…
    Just wanted to say thanks for posting this, and point out that method #2 can be used for more than just generating javascript or css.
    Say you are building a plugin that accepts POST requests from an outside source (i.e. PayPal IPN listener) and you want to use plugin options or $wpdb in manipulating the POST data. Instead of putting your data processing functions in a separate file and using wp-load.php, you can build them into the plugin file using method #2 and set the listener URL to http:www.example.com/?ipn_trigger=1
    Less files to worry about, no wp-load.php tomfoolery, and no “double-loading” of wordpress.

  19. Right Way the Second hook is done so late in execution… including wp-load.php is much faster

    But is there a hook that gets executed earlier??

    • Using *any* hook is always faster than including wp-load directly, because if you include wp-load directly, then your code doesn’t execute until after it’s finished loading up everything. Hooks happen during the load process.

  20. wp_localize_script is definitely the best way to go! Although the name doesn’t intuitively indicate it’s “made” for passing values to a script.

  21. Hi Otto,
    I found this snippet:

    from http://css-tricks.com/css-variables-with-php/ for fetch the var from smof theme option and I inserto in the head of style.php file.

    I load the dynamic css in the head of theme with this function:
    function kiwi_enqueue_css() {
    wp_register_style(‘options’, get_template_directory_uri() . ‘/css/styles.css.php’, false, null);
    wp_enqueue_style( ‘options’);
    }
    add_action(‘wp_print_styles’, ‘kiwi_enqueue_css’);

    It work fine, but after reading your article, I had a doubt, this charging wp_load.php right? So I can not use it? Right?
    the results: http://www.sitiweboristano.it/kiwiadv/

    Thanks a lot in advance, Davide

  22. Hi Otto,

    I have file in the plugin, when someone browse the file, i want to do some DB action (like update some filed in the plugin table). Below is my code. its working perfectly. but am including wp-config.php on file header. is there way to do this with out adding wp-config.php in header. any option to get the DB login details in this file.??

    ————————————————————————————
    $abspath = dirname(__FILE__);
    $abspath_1 = str_replace(‘wp-content/plugins/email-posts-to-subscribers/job’, ”, $abspath);
    require_once($abspath_2 .’wp-config.php’);

    $noerror = true;
    $form['delvid'] = isset($_GET['delvid']) ? $_GET['delvid'] : 0;

    if(is_numeric($form['delvid']))
    {
    global $wpdb;
    $sSql = “Call some SQL query to update the status”;
    $wpdb->query($sSql);
    }
    ————————————————————————————

  23. I found the solution. thanks…

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=""> <strike> <strong>

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