Using PHP Lambda Functions with WordPress add_action() and add_filter() Functions

I’m a fan of anonymous functions and reusable function definitions, like PHP lambda functions in JavaScript.  I’ve used anonymous functions in WordPress development where possible, so for example:

add_filter('widget_text', function($html) {
  if( strpos($html,'<?php') !== false ) {
    ob_start();
    eval('?>' . $html); // Close the current PHP tag...the contents we'll get will have <?php ?> tags itself
    $html = ob_get_contents();
    ob_end_clean();
  }

  return $html;
}, 100);

Instead of:

add_filter('widget_text', 'execute_php_in_widget', 100);
function execute_php_in_widget($html) {
  if( strpos($html,'<?php') !== false ) {
    ob_start();
    eval('?>' . $html); // Close the current PHP tag...the contents we'll get will have <?php ?> tags itself
    $html = ob_get_contents();
    ob_end_clean();
  }
  return $html;
}

There are only certain times where it’s best to create your own function to reference it, and that’s when you want to remove that filter or action later.

OK, so what’s the big deal about lambdas?  Here’s a scenario where it really stood out to me that this would be what I wanted to do.  I was working on a project where I needed to add filters for the custom taxonomies in a custom post type in the WordPress admin.  There are 2 hooks necessary to 1) create the drop down, and 2) to filter the actual query to show the results.  We currently have 4 custom taxonomies, so that would be 8 functions, each 2 repeated over and over for the 4 taxonomies.  Here’s a solution that creates a reusable function where you pass in the $post_type and $taxonomy slug.  To my knowledge, all you need is to be running PHP 5.3 or newer on your server.

$restrict_manage_posts = function($post_type, $taxonomy) {
    return function() use($post_type, $taxonomy) {
        global $typenow;

        if($typenow == $post_type) {
            $selected = isset($_GET[$taxonomy]) ? $_GET[$taxonomy] : '';
            $info_taxonomy = get_taxonomy($taxonomy);

            wp_dropdown_categories(array(
                'show_option_all'   => __("Show All {$info_taxonomy->label}"),
                'taxonomy'          => $taxonomy,
                'name'              => $taxonomy,
                'orderby'           => 'name',
                'selected'          => $selected,
                'show_count'        => TRUE,
                'hide_empty'        => TRUE,
            ));

        }

    };

};

$parse_query = function($post_type, $taxonomy) {

    return function($query) use($post_type, $taxonomy) {
        global $pagenow;

        $q_vars = &$query->query_vars;

        if( $pagenow == 'edit.php'
            && isset($q_vars['post_type']) && $q_vars['post_type'] == $post_type
            && isset($q_vars[$taxonomy])
            && is_numeric($q_vars[$taxonomy]) && $q_vars[$taxonomy] != 0
        ) {
            $term = get_term_by('id', $q_vars[$taxonomy], $taxonomy);
            $q_vars[$taxonomy] = $term->slug;
        }

    };

};

Now, what makes this super powerful, is when I want to add the filtering for the taxonomy, I just need these few small lines of code:

add_action('restrict_manage_posts', $restrict_manage_posts('resource', 'resource-type') );
add_filter('parse_query', $parse_query('resource', 'resource-type') );

And if I want to add another filter, it’s just a few small lines again – versus having to copy and paste the same functions over and over, changing just the $post_type and $taxonomy variables.

add_action('restrict_manage_posts', $restrict_manage_posts('resource', 'data-format') );
add_action('parse_query', $parse_query('resource', 'data-format') );