Use the WordPress Heartbeat API

A new WordPress performance bottleneck is looming:  admin-ajax.php.

More and more plugins are relying on the admin-ajax.php and the wp_ajax_ hook to deliver their content and functionality making WordPress more dynamic than ever. The problem is that if you have multiple plugins running all making their own wp_ajax calls without concern for what the others do, you end up with 4 or 5 server requests being required to render one page. This is a nightmare for server admins, especially since wp_ajax_ is often implemented as a POST request which allows it to bypass caching from cloudflare or varnish or what have you.

The solution is not to abandon wp_ajax_ but to come up with a better way to manage it. I really like what the Heartbeat API is doing. Instead of each client plugin managing it’s own request, you can tie into an existing “heartbeat” to get the info you need. I would recommend all plugin and theme developers use the Heartbeat API approach if at all possible. At least until wp_ajax_ gets  streamlined.

WordPress Hack: Reorder the Admin Menu

For many small business clients pages wind up being the most important WordPress post type. Many of them don’t even want a blog, just a nice looking site where they can update the content periodically, i.e. the contact page, the services page etc.

So for these clients it’s often a little confusing to have “Posts” at the top of the nav menu. Here’s how you would reorder to the nav to put pages on top.

First turn on the custom ordering option:

add_filter('custom_menu_order','__return_true');

Then create a function to filter the menu order array. In the function below we’re using array_splice to cut out the menu starting at position 2 because the “posts” menu item is #3 by default. How did I know that? Just add print_r($menu) and you’ll get a dump of the menu order. After splicing the array, we iterate over the old menu array, the part we extracted ($old), using a foreach loop adding the old menu items back in.

function mc_menu_order($menu) {
// more on array_splice here: https://php.net/manual/en/function.array-splice.php
$old = array_splice($menu,2,count($menu),array('2'=>'edit.php?post_type=page'));
$keys = array_flip($menu);
foreach($old as $item) {
if(!array_key_exists($item,$keys)) {
$menu[] = $item;
}
}
unset($old);
unset($keys);
return $menu;
}

Then just add the api call to insert that function:

add_filter('menu_order','mc_menu_order');

Here it is all together:

//menu reorder
add_filter('custom_menu_order','__return_true');
add_filter('menu_order','mc_menu_order');
function mc_menu_order($menu) {
$old = array_splice($menu,2,count($menu),array('2'=>'edit.php?post_type=page'));
$keys = array_flip($menu);
foreach($old as $item) {
if(!array_key_exists($item,$keys)) {
$menu[] = $item;
}
}
unset($old);
unset($keys);
return $menu;
}

Registration Forms: What’s New in 1.5

Last week I released version 1.5 of my Simplr Registration Forms plugin. The new version includes some big fixes and requested features. Particularly, this version now supports WP Multisite and has a few addition profile fields that can be added to the default form. It also includes better security, via WP nonces, and better field validation.

But the most important change is that it includes hooks and filters that allow it to be extended by you, the user.

For instance, let’s add a field to our form that requests the user’s zip code. First, in your functions.php file create a function for displaying the field:

function sample_zip_field($form) {
 $form .=  '<div>';
 $form .=  '<label for="zip">Zip Code:</label>';
 $form .=  '<input type="text" name="zip" value="'.$_POST['zip'] .'"/><br/>';
 $form .=  '</div>';
 return $form;
}

Note that this function receives the parameter $form and then returns $form. Failing to return the form will make the entire registration form disappear. To add this form to the registration use:

add_filter('simplr_add_form_fields', 'sample_zip_field');

But then we also need to make sure this data gets saved when the for gets saved. So you’ll need to create a function for that as well.

function sample_save_meta($user_id) {
if(isset($_POST['zip'])) {
 add_user_meta($user_id, 'user_zip', $_POST['zip']);
 }
return $user_id;
}

Note that in order for this function to work properly it has to receive the $user_id. It is also good practice to return the $user_id at the end of the function, though not necessary.

To make sure your save function is called use the hook:

add_action('simplr_profile_save_meta','sample_save_meta');

With these two “hooks”, you can customize the registration form however you want. You could even set up your field function to only display on certain pages, making it form-specific.

Finally, I’ve also added filters to the labels on the default form fields so you can change them at will. For instance, to change username to “screen name” use the following.

function sample_label_username($label) {
 $label = "Screen name: ";
 return $label;
}
add_filter('simplr_label_username','sample_label_username');

I hope you find the changes useful.