Quick WP Tip: paths and URLs in WordPress

I was reading an article on Sitepoint about custom write panels the other day when I got heavily annoyed. The direct reason for this was one of their code examples and the authors apparent incomplete knowledge of the WordPress API’s most basic functions and constants. In that example, he does the following:

define(
  'MY_WORDPRESS_FOLDER',
  $_SERVER['DOCUMENT_ROOT']  
);  
define(  
  'MY_THEME_FOLDER',  
  str_replace("",'/',dirname(__FILE__))  
);  
define(  
  'MY_THEME_PATH',  
  '/' . substr(  
    MY_THEME_FOLDER,  
    stripos(MY_THEME_FOLDER,'wp-content')  
  )  
);

That annoyed me, quite a bit. Why? Well because if people write articles about stuff like custom write panels, I expect them to know a bit about the basics of the WordPress API. And well, the WordPress API has constants and functions for these things. So let me introduce you to them in the same order as the author of the articles did his defines above:

ABSPATH constant

Not only is their method inconvenient, it’s wrong for a lot of installs. You see, some people install WordPress in a subdirectory, and depending on what you need, there are two different paths you might need. ABSPATH is a constant that always returns the home of WordPress. So if WordPress is in the wp/ subdirectory, it would give you something like: /home/username/public_html/wp/. If WordPress were installed in the root, it would just return /home/username/public_html/. Now I don’t know how they’re using it, as it’s not used in this particular article, but they’d have to be very cautious with that.

TEMPLATEPATH constant

The second two things they’re doing are possibly even weirder. First they define a constant MY_THEME_FOLDER, which is basically the path to the current theme. WordPress has a very convenient constant for that: TEMPLATEPATH. Since they’re using it in an include, that’s probably what they need. Would save about 4 lines of code. Note that what they call a “folder” is actually a path.

get_template_directory_uri()

This is were they really go wrong. You see, they define a constant MY_THEME_PATH, and then use it as a URL in a call to wp_enqueue_style(), in other words: to enqueue a style sheet. Now paths and URLs are different animals altogether, and they don’t mix well. Take this example:

  • My blog is installed in a subdirectory /wp/
  • Because of that MY_THEME_FOLDER has been defined as follows:
    /home/user/public_html/wp/wp-content/themes/example-theme
  • The code that sets MY_THEME_PATH turns that into:
    /wp-content/themes/example-theme
  • The stylesheet is now included with the following path:
    /wp-content/themes/example-theme/custom/book_panel.css
  • This causes a 404 (file not found error) because that directory simply doesn’t exist! It should have been:
    /wp/wp-content/themes/example-theme/custom/book_panel.css

The proper way of doing the enqueue would thus have been the following:

wp_enqueue_style(
    'my_meta_css',
     get_template_directory_uri(). '/custom/book_panel.css'
  );

Conclusion

I hope you understand why this annoys me. This is exactly the kind of coding that gives WordPress coders out there a bad name, as 5 – 10% of people out there trying this will not get it to work. If you want to prevent from making such mistakes, there’s plenty of resources to learn about these things, or look them up. Two starting points would be the codex and my own cross reference of the WordPress source along with its very convenient WordPress source search function.

Tags:


Yoast.com runs on the Genesis Framework

Genesis theme frameworkThe Genesis Framework empowers you to quickly and easily build incredible websites with WordPress. Whether you're a novice or advanced developer, Genesis provides you with the secure and search-engine-optimized foundation that takes WordPress to places you never thought it could go.

Read our Genesis review or get Genesis now!

8 Responses

  1. Niels BrinchBy Niels Brinch on 2 September, 2010

    Way to go, showing off your superhuman WordPress skills.

    Wouldn’t it be appropriate for you to educate them by leaving a comment on that article?

    • Joost de ValkBy Joost de Valk on 2 September, 2010

      That’s what trackback and pingback are for :)

    • RobertoBy Roberto on 2 September, 2010

      That’s what trackback and pingback are for :) [2]

  2. Desi MatlockBy Desi Matlock on 2 September, 2010

    Well explained. Thanks!

  3. paulBy paul on 2 September, 2010

    I use WP_CONTENT_URL

    wp_enqueue_script('my_script', WP_CONTENT_URL . 'themes/my_theme/
    my_script.js', array('jquery'), '1.0.0');

    • ProactolBy Proactol on 4 September, 2010

      Still, you are hardcoding the ‘themes’ part which you shouldn’t really :p

  4. MarkBy Mark on 4 September, 2010

    Thanks again Joost. Yes, we’re all human.

    I can certainly emphasize with how you felt annoyed. A couple weeks ago I started using your Simply Taxonomies plug-in and it’s not performing as “promised”. Apparently, it’s not possible to change the slug values via your plug-in once they are set. Yet the plug-in does not make warming about this and even pretends that it’s dobale. Posting to the WP forum has yet to get a reply. That’s annoying too, eh?

    Or maybe you were annoyed like I am with this comment box STILL now wrapping the text input correctly. It hurts me to think that you’re not as more perfect as I want to believe you are.

    Joost, you are obviously a very talented individual. We always appreciate that. But you, like the rest of us, do not walk on water. Please, take it down a notch already. Take for a while your trumpet from you lips and sort out the issue mentioned. That would then be actual proof your superior position in our world. ;) As it is, your horn blasts are more annoying than vuvuzelas. lol

  5. MarcusBy Marcus on 8 September, 2010

    Another addition to the list of reasons why plugins fail :)

    Worth noting get_stylesheet_directory_uri() as well. get_template_directory_uri() will return the directory of the active theme, but will also return a parent theme if yours is a child. If you have a child theme, you should use get_stylesheet_directory_uri() to access that directory.

    locate_template is also good for locating files in a theme.