Function Documentation

WordPress Function Documentation Progress

Writing WordPress Widget Best Practices

Don’t Nest Functions

It appears to be a neat trick, but that is all it is. A hack that you should avoid and just because you can do it and it works does not give reason to do so. There are many programming practices that you can use in PHP, but must not. The only exception was, if you were the only one that is going to see it and it was an exercise of academics. Aside from that, the common widget practice of nesting functions inside of functions should be halted.

Example of Wrong Widget Form

function myplugin_widget_init()
{

    function myplugin_widget_display($args)
    {
        
    }

    function myplugin_widget_control()
    {
        
    }

    // Register myplugin_widget_display() and myplugin_widget_control()
}

The problems with this code are listed below.

  1. Class structure would be the most logical alternative.

    The simple containment of the functions is easily accomplished using a class container. I’m unsure what the appeal of this form, but if the need to contain the three functions, than a class should have been used instead.

    I have an theory, that the first one to use this pattern knew what he/she was doing and thought it would be cool and didn’t realize that everyone else would use it as an example. Everyone else that came after noticed that it worked (mysteriously) and decided that it was easier than learning OOP. However, this theory is unproven, so whatever the reason, a class would have been a better and wiser choice.

  2. Prevents Opcode Caching optimization.

    PHP will not compile the two functions contained in myplugin_widget_init() until that function is called. By halting the compile process, some one using an Opcode Cache will not receive the boost. Furthermore, PHP will not know in most cases whether it will need to continue to cache the two functions, so at the best case the functions will be cached after the function is called and at the worst case, it will have to compile the two functions with each process.

  3. Causes fatal duplicated function definitions.

    In the event that myplugin_widget_init() is called twice, it will cause PHP to try to compile the contained functions twice. This will fail, because PHP already compiled the functions when the function was called the first time. The reason you won’t have a third call is that the second call will bring PHP and WordPress crashing down.

Widget Best Practice: Using the Object Pattern

class myplugin_widget
{
    function init()
    {
        // Register myplugin_widget::display() and myplugin_widget::control()
    }

    function display()
    {
        // Echo content
    }

    function control()
    {
        // Echo administration control
    }
}

I like keeping functionality contained together. Some plugins choose to dump all functionality into the same object, I would advise against this, but if it is easier for you, then just use functions instead until you learn OOP better.

Widget Best Practice: Using Functions

function myplugin_widget_init()
{
    // Register myplugin_widget::display() and myplugin_widget::control()
}

function myplugin_widget_display()
{
    // Echo content
}

function myplugin_widget_control()
{
    // Echo administration control
}

This code is far nicer looking and contained and has none of the disadvantages listed above.

Advertisements

February 4, 2008 Posted by | Writing Plugins Series | , , | 1 Comment

wp-config.php Settings: Part 2

About WP_MEMORY_LIMIT

In WordPress 2.5, a new hard coded setting is added, which allows for increasing the memory limit. Few people always seem to have a problem where PHP exhausts all of the memory (usually 8MB) and PHP crashes, bringing down WordPress in the process.

By default, the memory is increased to 32MB, which is conservative or liberal depending on your hosts setting. Dreamhost has 128MB for PHP5, which is pretty crazy, but if a PHP program takes up all of that, then there is something seriously wrong with the application. WordPress should be able to run within 32MB on small and medium sized blogs with just the default caching.

This won’t solve all of the problems, because some hosts do not have memory limit setting enabled. In order for the increase to work, --enable-memory-limit had to be set during PHP installation and ini_set() has to be enabled (not part of the disabled_functions PHP INI setting). Nothing that WordPress, nor the user has control over. If --enable-memory-limit was not used, then the host can’t even increase the memory limit. Some hosts do disable the ini_set() function for security and PHP configuration purposes.

However, the good news is that unless you screwed up your PHP installation (and should reinstall and upgrade anyway) or on a crappy host, you should be okay and the increase will take affect.

Note: Don’t worry about the constant lowering the memory limit, because it won’t try to set the memory limit if the defined constant is less than what is already set in PHP.

Setting WP_MEMORY_LIMIT

In your wp-config.php file, insert the following:

define('WP_MEMORY_LIMIT', '32MB');

Just basically copy the above and the memory limit will be attempted to be set to ’32MB’. You can change ’32MB’ to any number of MiB in the format of a number, followed immediately by ‘MB’. So other examples are ’16MB’ (PHP5 default), ’64MB’

define('WP_MEMORY_LIMIT', '16MB'); // PHP5 default
define('WP_MEMORY_LIMIT', '67MB'); // Larger Blogs using default object cache. Just in case.

Criticisms

WordPress continues to work on improving the amount of memory that is required. It is impossible to optimize the WordPress Object Cache on large blogs and may never be. It is with that reasoning that the above addition is justified. If 32MB isn’t enough, just increase the memory limit and let the WordPress team know it failed.

January 31, 2008 Posted by | Advanced User Manual | , , , | 1 Comment

Writing Plugins: Don’t Place All Methods in One Object

Objects should only contain a single purpose, but most plugins I’ve seen pack every method in a single object. This opposed to splitting the methods out into better logical objects which contain that purpose and allow reuse across multiple projects. I would like to instead propose a better way to write objects, which don’t violate the advantages and purpose of objects. Packing everything in the same object did cause problems prior to WordPress 2.3.

I believe the reason that plugin authors have for placing all of the methods in the same object is:

  1. To keep the plugin contained for the user.
  2. That it is easier to access all of the methods and properties.
  3. Place all data and methods in a single namespace.

Objects are supposed to solve the question of reuse. It should seem reasonable that if plugins were decoupled objects, then it would be possible to easily create that same plugin for another PHP application. That is probably not the intention of the plugin author, but it could be another user’s or mine.

A solution for plugins which do this, is to inherit the object and override the methods and data you need to change. I did this with a recent plugin, which allows me to upgrade the plugin’s code without having to make the same changes over and over again.

The general rule I keep is when I’m building a class is either to plan out what methods each one it going to have and what properties and finally how each will interact with the other. If you must jump in and code without planning then once you reached a point where you are adding methods and properties that fall outside the scope of the original functionality then stop and ask, “How can I refactor this?”

For me, it is a constant question I ask about my code, because unless you’ve been coding objects for most of your life, there can always be improvements made. Decoupling your code also has the advantage of allowing you to reuse, which is key with objects and functions, in another plugin or project.

Most plugins that I’ve seen are coupled and can not easily be refactored without an almost complete rewrite of the core systems. If this is the case, then good luck and I wish you the best for your plugin.

Better Standard

I personally don’t use classes for my plugins. However, if I were to use objects, I would do it in this matter.

I would have a single class for the activation, deactivation, and init hooks.

class MyPlugin_Core
{
    function activation_hook()
    {
        // Do activation stuff
    }

    function deactivation_hook() {  }

    function init_hook() {
        $objMyPlugin = new MyPlugin_DoesSomething();

        // Do stuff with MyPlugin_DoesSomething
    }
}

register_activation_hook( __FILE__, array('MyPlugin_Core', 'activation_hook') );
register_deactivation_hook( __FILE__, array('MyPlugin_Core', 'deactivation_hook') );

add_action( __FILE__, array('MyPlugin_Core', 'init_hook') );

More of how you should structure your plugins in a later post.

Updated: An object is an object and a singleton is an object which only returns one reference to itself. With objects, you can create any number, but the Singleton pattern restricts creation to only one. Thanks to Jamie Talbot for the correction!

January 16, 2008 Posted by | Writing Plugins Series | , , | 5 Comments

Writing Plugins: What is the Class Callback Format?

Prior to WordPress 2.3.0, there was a bug that prevented object referenced method callbacks from being removed. In WordPress 2.3.x and upcoming WordPress 2.5, in order to remove the original method in the class, you have to use the original object reference. In PHP4, where objects are passed by value, this can be a problem, but PHP5 users shouldn’t have much to worry about as long as the variable they are using holds the original class reference.

Explanation of Problem Prior to WordPress 2.3

To demonstrate the problem, take a look at this code. If you were to run this prior to WordPress 2.3, the hook would not be removed because you changed the class property $test.

class MyPlugin
{
    var $test;

    function MyPlugin() {
        $this->test = false;
        add_action('init', array(&$this, '_init'));
        $this->test = true;
    }

    function init() {
        remove_action('init', array(&$this, '_init));
    }
}

This is a poor example, in that the ‘init’ hook will never run again. Other hooks will demonstrate the problem better in real world practice. That said, the method of adding callbacks to the hook array wouldn’t have allowed you to remove the hook until the state of the class was back in its original form prior to the addition of adding the MyPlugin::_init() to the init hook.

It is a little complicated to explain, but basically, once you changed the properties of the class, you wouldn’t be able to remove any hook you added prior to the change. For most plugins this was a huge deal since they had everything in one Singleton class (big mistake, will detail in later post).

How Method Callbacks are handled in WordPress 2.3+

A new private function was introduced to manage object referenced method callbacks. The form of which is below.

$myplugin = new MyPlugin();

add_action( 'init', array(&$myplugin, '_init') );

As you can see, the callback references the $myplugin variable along with the method in the second element. The reason this can cause a problem, is if you unset the variable afterwards.

$myplugin = new MyPlugin();

add_action( 'init', array(&$myplugin, '_init') );

unset($myplugin);

If you think this will magically remove the reference in the hook array, you are mistaken. PHP will retain the reference to the object and will call the method. This will hinder, but not prevent the removal of the object’s callbacks later.

For a workaround, you can recreate the object reference and it should (purely conjecture) recreate the needed hook string to reference to previously added object reference callback. This will not work if two or more object references of the same class were created, so it is assumed that in most cases only one object reference will be created. If only one were created and destroyed, it might be possible to remove the callbacks from the action or filter using the Plugin API.

New format

The new format for the above object referenced method callbacks are always: class name, followed immediately by the method name, followed by the amount of previously added (classname+methodname). For classes, this allows you to add as many object referenced classes and add methods which don’t override each other.

For static method callbacks, the format is always: class name followed immediately by method name. There is no need to protect against overrides because no two classes can have the same class name (yes, I do know there is an exception to this rule).

For functions, nothing changes, it is just the function name.

January 13, 2008 Posted by | Writing Plugins Series | , , , | 5 Comments

Ohloh No Longer Criticizes WordPress Comment Ratio

Ohloh no longer lists the comment to code ratio as a factor for WordPress! This will hopefully improve as the PHP code base continues to be documented. Hopefully, once the focus is moved over to automated testing, the bugs and functionality will be improved to the point where WordPress will be rock solid.

This will hopefully limit the overall criticism that other developers have on WordPress. It will be a long road for complete documentation and quality assurance in WordPress. It is both fun and worthwhile learning experience. It is something that should have been in WordPress since the early days, but that isn’t important.

What is important is that not only should the quality of the WordPress feature set and defects reduce but the overall quality and assurance of that quality should be improved.

January 12, 2008 Posted by | WordPress | , , , , | Leave a comment

Informal Roadmap: Step 2 Completed

All items that could be documented in wp-includes folder has been documented with @since phpdoc tags. Which will allow for staying in that one file instead of going back and forth from web browser with version information to the editor. Will save time, I believe.

All that is left now is basically the following.

  1. Short Description
  2. Return type and description
  3. Parameter type and description
  4. Long Description

Now that the second step is completed, I’m going to focus more on completing the following files below. During that, I’m going to create tickets for the remain incomplete files that I’m not going to seek to finish. In that arena, there are only 20 incomplete files in wp-includes folder. If I complete the following files, I can get that number down to a more manageable 14. So that the next person that comes along shouldn’t feel a lot of weight on their shoulders.

In no particular order, I want to complete these files before the 14th of January 2008 is up. If I can complete at least 3, then I’ll be happy.

  • kses.phpalmost complete
  • pluggable.php – almost complete
  • comment.php – almost complete
  • cron.php
  • category.php
  • user.php

The most logical course of action is to finish up the almost complete files and have them committed as completed. Then start working on the rest of the easy files which shouldn’t take very long to complete. Probably should get cron.php started first since it is one of the most difficult with extremely sparse documentation. The category and user files will be worked on, in the event that there is more time left over.

So the goal jumped from 3 finished, to 4 finished and in one weekend. Wish me luck.

January 12, 2008 Posted by | WordPress | , , , , | Leave a comment

Writing Plugins: The ‘all’ Hook

The ‘all’ hook is run on every action and filter hook. It is good for debugging and not much else. Also, prior to WordPress 2.5, the ‘all’ hook was broken and shouldn’t be hooked into.

The fix removes the logic that merges the all hook into the rest of the other hooks. This should have a nice benefit of speeding up the plugin cycle. The all hook will also only be processed if there is a function that was added to it. For almost all users, they will never run the all hook.

The ‘all’ hook is technically an action since it does not offer an interface for returning data to other functions that are in the ‘all’ hook. However, it will run for all actions and filters, but will not have access to the filter contents.

Well, for filters, the ‘all’ hook will have access to the initial parameter value or values if there is more than one parameter (more on that later), but will not have access to the completed value after all of the functions in the hook have processed the initial value.

Adding a Function to the ‘all’ Hook

add_action('all', 'myplugin_all_hook');

function myplugin_all_hook( $parameters ) {
    // Do stuff here
}

The all hook has access to the parameters that were passed to the hook as an array and that will be passed to the functions. The ‘all’ hook does not have access to manipulate those parameter values before they get to the filter or action functions.

The $parameters is an array, which holds all of the values for from each of the parameters. You can count the array, test the contents of the parameters, test the types of the values.

Use Cases

What the ‘all’ hook can do however is a few evaluations.

  1. Do sanity checks against how many parameters the current hook (Will be discussed in a later post) should have verses how many were actually passed.
  2. Count how many times a hook was called during a run of WordPress and for each page. (The ‘all’ hook will not be able to profile how long each hook took to process however.)
  3. Using debug_backtrace(), can figure out which functions called the hook.
  4. Fine tune your plugin by seeing what the hook you are plugin to is giving your function.

Those are the common use cases of the ‘all’ hook. However, like it has already been stated, only debuggers are likely to plugin to the ‘all’ hook. Most plugin authors and users should not concern themselves. However, if you wish to debug the hooks, then there is a built-in way to do so.

January 10, 2008 Posted by | Writing Plugins Series | , , , | Leave a comment

State of WordPress Documentation

The Codex

Perhaps the most definitive guide for WordPress is the codex and perhaps the few books that are out. However, the books can never cover the full scope of all that is WordPress. The codex focuses on a lot of subjects that is WordPress but does not cover everything that a user and developer needs.

That is probably the biggest problem with both the codex and books. What do you cover? What should be covered. Do you hold the user’s hand for the first few steps or do you ride the whole way making sure that the user stays on the correct path? For the codex, it is the former, it only holds your hand for a little while and the contents of which you have to find yourself.

That is not to say that the codex isn’t the best resource you have. It is. It is only to say that it will only take you so far before you have to help yourself.

Debate Against WordPress Inline Documentation

There shouldn’t have been a debate, early on in whether inline documentation should be included in the core. Before late 2006, early 2007, the consensus from the core team was that inline documentation wouldn’t make it into the official WordPress repository. Attempts to add inline documentation were blocked and that was a big mistake.

It is only speculation, but in my opinion by blocking the potential authors of said documentation, they essentially killed their motivation to do it. Those that initially started would shot down before they were able to prove whether or not they could complete the documentation. It would be another year before another person would come along. Like anything it is unknown whether that person would be able to complete all of the documentation before moving on to something more shiny.

It created other problems, because created debates about adding documentation. Which to long readers of the WordPress hackers list, seemed redundant, because the subject had been beaten to death many times before. There was even a debate over the standard of inline documentation, when a standard already existed before the debate started. It was time that would have been better spent following the current standard and working on the documentation.

That discussion was in October 2007 and there were many discussions before that. The codex page for Inline Documentation lists a few, but not all.

Current Effort

The current effort was picked up in October of 2007 and ended January 2008. A large amount of functions were documented, but it is far from complete. The wp-admin/includes folder also needs to have a phpdoc effort started for it.

It seems that every six months or so, discussion picks up and motivation is gained for completing the documentation, so perhaps in six months to a year some awesome person will come along again and finish the effort that has been started by so many people.

January 9, 2008 Posted by | WordPress | , , , | Leave a comment

Writing Plugins: Activation and Deactivation

WordPress provides hooks for when the plugin is activated and deactivated. Some plugins will have logic in their init function which check to see if set up or installed itself and if it didn’t it would install or upgrade itself.

The upgrader check can still remain in the init function, a user might have not deactivated the plugin before uploading the new files. The installer can be placed in the activation hook which can check if the plugin had been installed and install if it hadn’t installed already. It can also check to see if it needs to upgrade, in case the user deactivated before uploading the new plugin files or had the plugin deactivated for some other reason.

Any amount of code for which can be moved to the activation and deactivation functions from the init function can save that much overhead and reduce the complexity of the init process.

Activation

function myplugin_activation() {
    $pluginOptions = get_option('myplugin_data');

    if ( false === $pluginOptions ) {
        // Install plugin
    } else if ( MYPLUGIN_VER != $pluginOptions['version'] ) {
        // Upgrade plugin
    }
}

register_activation_hook(__FILE__, 'myplugin_activation');

It is really that easy. WordPress provides a convenience function for hooking into the plugin’s activation hook, no matter where the plugin is located. If your plugin is moved from its directory structure, then if you manually hooked into the activation action, you might not be hooking into the right one. There is a way around that problem, but it is easier to just use register_activation_hook() instead.

Deactivation

The deactivation is easier, but most plugins don’t need it. You can be annoying and prevent the user from disabling your plugin, but they’ll get wise to your deception and remove your plugin, if you choose to do that. It would be unwise to include anything in your plugin that might discourage further usage and users.

It will be useful if you wish to include an uninstaller, in case your plugin creates new tables or adds options or whatever else that may need to be cleaned up. The topic of building an uninstaller is for another day, right now, it is one idea in case you have other needs or ideas for it.

function myplugin_deactivation() {
    $pluginOptions = get_option('myplugin_data');

    if ( true === $pluginOptions['uninstall'] ) {
        delete_option('myplugin_data');
    }
}

register_deactivation_hook(__FILE__, 'myplugin_deactivation');

Again, WordPress provides another convenience function for the deactivation of your plugin. The logic for the deactivation is a lot less than the activation in most cases.

January 8, 2008 Posted by | Writing Plugins Series | , , , | Leave a comment

Writing Plugins: Put all logic in functions

The only code that should be outside functions are the hooks into activate, deactivate, and init hook. A plugin should not assume that it can put HTML and echo blocks outside of functions, because the HTML and logic will display before WordPress is initiated.

The explanation for this is the plugins are included into the process after all of the WordPress library files are included, but before the rest of WordPress is set up. The reason to hook into the ‘init’ hook is that is when WordPress is finished setting everything up and is called at the very end of the wp-setting.php file.

Every plugin should have this code structure:

function mynamespace_init() {
    // hook into all needed filters and actions
}

add_action('init', 'mynamespace_init');

What You Should Never Do

  1. if( WordPress is Setup ) {
        echo "I'm evil
    "; }

    This will always fail, because there is no way to figure out if WordPress is ready for output without using the Plugin API.


  2. require ( ABSPATH . WPINC . '/plugins.php' );

    This will cause WordPress to fail since plugins.php is already included at the time your plugin is included. You should never include WordPress library files! The exception to this might be the admin library files, but you should always check for the function you want before trying to include the file and should always check the inclusion path inside the admin page you’ll be hooking into.

January 7, 2008 Posted by | Writing Plugins Series | , , | 1 Comment