Deprecated functions and WP_DEBUG

(Updated June 27, 2010: You may wish to check out my Log Deprecated Notices plugin.)

In every major version, the WordPress developers send functions to the graveyard. Many developers continue to use deprecated functions in their pluigns, or may even begin to use a function after it was already deprecated.

Deprecated functions cannot be relied upon to work efficiently or correctly and may be disabled by default or entirely removed in future versions of WordPress. But really, I would think about it like this: By using them, you’re likely missing out on new features afforded by the new function.

There are various reasons we deprecate functions:

  • We may decide to change or improve how it the function works, but doing so might break backwards compatibility. So we deprecate the old function and come up with a new one.
  • We may rename a function to standardize its name with other functions or to clarify its usage. Developers tend to like APIs standardized as much as possible, as it means we can work faster.
  • We may consolidate functions — for example, the_author_meta($meta) and get_the_author_meta($meta) replaced 25 functions.[1] Yes, 25. And it can return any usermeta field. current_user_can(), likewise, replaced a bunch of functions along the lines of user_can_create_draft() and user_can_edit_post_date(). In another example, we’re consolidating category and tag operations under term/taxonomy operations.
  • We may remove functions that no longer do anything. (Why do we keep a function that doesn’t do anything? If a plugin tries calling a function that no longer exists, you’ll get a fatal error. Also, if a plugin uses the same function name in a later version, the plugin would be incompatible on an old version that has the function.)
  • When merging in WordPress MU in 3.0, we removed dozens of functions, in many cases to merge them with their non-MU counterparts.

We normally don’t deprecate functions when we change front-end terminology, as we trust developers to make the connection, and we’re not nuts enough to rename functions just for the sake of renaming them.

What else do we deprecate?

We also don’t have just deprecated functions. We have deprecated files and, as of 3.0, deprecated function arguments.

Deprecated files: MagpieRSS (wp-includes/rss.php) has not been developed for years, and is deprecated in favor of Simplepie (wp-includes/class-simplepie.php). Most others were files that have been renamed, but we had to keep the old one because they were ones often included directly by plugins. In these cases, the old file includes the new files, so you don’t lose functionality. Deprecated files include:

  • wp-includes/rss-functions.php, now wp-includes/rss.php (also deprecated; use Simplepie)
  • wp-includes/registration-functions.php, now wp-includes/registration.php
  • wp-admin/upgrade-functions.php, now wp-admin/includes/upgrade.php (contains wp_install(), dbDelta(), etc.)
  • wp-admin/admin-functions.php, now wp-admin/includes/admin.php
  • WordPress does not support the legacy my-hacks.php file

Deprecated arguments: (new in 3.0) In nearly all cases, deprecated function arguments no longer have any functionality tied to them and often don’t have alternatives available. If we later add an argument to that function, though, we don’t want to take the spot of an argument that used to be there, in case a plugin developer still tried using the original argument.

Where we keep them

Deprecated files and arguments are scattered throughout core, but we consolidate deprecated functions so developers can reference those files. In 2.9, the file was wp-includes/deprecated.php. In 3.0, we now have five files:

  • wp-includes/deprecated.php — Regular WordPress functions available everywhere.
  • wp-admin/includes/deprecated.php — For WordPress functions only usable in the administration area.
  • wp-includes/ms-deprecated.php — Functions from WordPress MU, loaded only when running multisite.
  • wp-admin/includes/ms-deprecated.php — Functions from WordPress MU only usable in the administration area.
  • wp-includes/pluggable-deprecated.php — Pluggable functions. Because pluggable functions are defined later (so a plugin can override them), we can’t put these in the normal deprecated.php file. Moving them into its own file allows us to lower their profile.

Keeping track of deprecated usage

As of right now in 3.0, we have 131 deprecated functions and 39 deprecated arguments. How should you, a plugin developer, keep up with them all?

define( 'WP_DEBUG', true );

If you’re a plugin or theme developer and you don’t know what the WP_DEBUG is, you’re missing out. (If you do know what it is and you don’t use it during development, you’re crazy.)

The WP_DEBUG constant, which you would define as true in wp-config.php, does two things. First, it tells PHP to report more errors, specifically “notices.” (WordPress normally instructs PHP to only report warnings and fatal errors.)

This means you will see potential problems in your code, such as unchecked indexes (empty() and isset() are your friend) and undefined variables. (You may even find problems in WordPress itself, in which case you should file a bug report.)

Second, WP_DEBUG exposes debug messages generated by WordPress, such as:

  • When a deprecated function or function argument is used, or a deprecated file is included.
  • When user levels are used instead of the roles and capabilities system.
  • When old APIs are utilized instead of new ones, such as the Settings API (register your settings!).

In a nutshell, there’s an entire API devoted to informing you of the best practices and the latest APIs. Here’s two example notices:

Notice: options.php was called with an argument that is deprecated since version 2.7! The “your_option_name” setting is unregistered. Unregistered settings are deprecated. See http://codex.wordpress.org/Settings_API

Notice: get_category_rss_link is deprecated since version 2.5! Use get_category_feed_link() instead.

You can suppress notices if you prefer, by using the WP_DEBUG_LOG and WP_DEBUG_DISPLAY constants (see the inline documentation I wrote here). You can also use hooks and filters in the Deprecated API (view the functions). (To know where functions are being run, you could run a backtrace on one of those hooks, for example.)

Many even run WP_DEBUG on their production websites. Generally, they log it (using either WP_DEBUG_LOG or a server PHP error log) and force the hiding of errors, using:

define( 'WP_DEBUG', true ); // turn on debug mode
define( 'WP_DEBUG_LOG', true ); // log to wp-content/debug.log
define( 'WP_DEBUG_DISPLAY', false ); // don't force display_errors to on
ini_set( 'display_errors', 0 ); // hide errors

“But I need to support old versions”

Honestly, I wished you didn’t ask that. But if you must support a legacy version, conditionally check for the new functions and use those if available.

// esc_url() introduced 2.8
$cleaned_url = ( function_exists( 'esc_url' ) )
	? esc_url( $url )
	: clean_url( $url );

 // introduced 2.8
if ( function_exists( 'wp_register_sidebar_widget' ) )
	wp_register_sidebar_widget( 'widget-id', 'My Widget', 'my_widget_callback' );
// introduced 2.2, if you must check
elseif ( function_exists( 'register_sidebar_widget' ) )
	register_sidebar_widget('My Widget', 'my_widget_callback' );

Just remember: friends don’t let friends develop plugins without WP_DEBUG.

[1] These functions were deprecated in favor of get_the_author_meta(): get_author_name(), get_the_author_ID(), get_the_author_aim(), get_the_author_description(), get_the_author_email(), get_the_author_firstname(), get_the_author_icq(), get_the_author_lastname(), get_the_author_login(), get_the_author_msn(), get_the_author_nickname(), get_the_author_url(), get_the_author_yim(). In favor of the_author_meta(): the_author_ID(), the_author_aim(), the_author_description(), the_author_email(), the_author_firstname(), the_author_icq(), the_author_lastname(), the_author_login(), the_author_msn(), the_author_nickname(), the_author_url(), the_author_yim().

Published by

Andrew Nacin

Lead developer of WordPress, living in Washington, D.C. Follow me on Twitter.

17 thoughts on “Deprecated functions and WP_DEBUG”

  1. Before WP_DEBUG, my life was bleak and meaningless.

    Now, WP_DEBUG has made all my wildest dreams come true!

    😀

  2. I just tried WP_DEBUG on a site I am building and lo-and-behold all the plugins I’m using on the site are throwing errors.

    WP_DEBUG is a great idea, but the community really needs to make noise to get all active plugin developers to embrace it otherwise it’ll just be too much trouble to use (which would be a damn shame.)

    1. We’re trying. As one example, see #12236 and http://core.trac.wordpress.org/changeset/13185. I added language in wp-config.php for new installs:

      /** 
       * For developers: WordPress debugging mode. 
       * 
       * Change this to true to enable the display of notices during development. 
       * It is strongly recommended that plugin and theme developers use WP_DEBUG 
       * in their development environments. 
       */ 
       define('WP_DEBUG', false);
  3. Is there a way to just show Fatal errors and ignore the warnings? On my development platform, whenever I suspect a fatal error, I need to turn wp_debug to true to see the error. I leave it off by default, otherwise I see too many notices I don’t need to see. Thanks.

    1. You dont need debug options for fatal error.
      Your website will tell that to you in most clear words 🙂

  4. Hi Andrew,

    For WP 3.0 and beyond, is the @ini_set('display_errors', 0); line needed if WP_DEBUG_DISPLAY is set to false? Just wondering because when I set WP_DEBUG_DISPLAY to false and comment out @ini_set('display_errors', 0);, I don’t see a difference versus when I leave it in there.

    I also did a little spelunking and in the load.php file on line 264 (WP 3.0.5) there is a check on WP_DEBUG_DISPLAY that then sets ‘display_errors’ to 1 if true. If you added the else statement to that check, to set ‘display_errors’ to 0, wouldn’t that eliminate the need for putting @ini_set('display_errors', 0); in wp-config.php entirely?

    –Dave

  5. hi i have a problem, where is trouble :

    Fatal error: Cannot redeclare username_exists() (previously declared in /home/buanacom/public_html/komputerbekas/wp-includes/registration.php:16) in /home/buanacom/public_html/komputerbekas/wp-includes/registration.php on line 22

    please help me

  6. Every site shows how to turn debugging on, but I can’t find anyplace that tells me how to emit something to the log. How can I write my own message into the log?

  7. I find code hard, so please forgive this question:

    What do I do with the deprecated calls your plugin reports? I seem to have around 450 across the theme (300+) and plugins (the remainder) used in my site. For example, I have the following:

    Function: get_settings()
    Used in wp-content/themes/wp-prosper/header.php on line 1.
    Use get_option() instead.
    Deprecated in version 2.1

    This is line 1 of that file:

    So could I replace get_settings in the above line with get_options and it would clear the warning and be more efficient? Or would this break the theme? Is this something I need the theme creator to address?

    For efficiency sake, I’m trying to clean up my WordPress install.

    thanks for any input

    1. seems my code disappeared there. Let me try again to give the first line of header.php as an example

  8. Im scanning through all the tutorials and blogs I can find re why the whole WordPress website/ blog that I am looking after is throwing errors.(front-end and back end) It is rellay annoying and my php knowledge is limited. Is there in any way a solution to simple web-developer like me to understand and fix this broken site 🙁

Comments are closed.