A few years ago I read an article about short-circuiting functions with apply_filters() rather than using pluggable functions via function_exists(). I love the idea because of how flexible it is- I'm not limited by when a function can be overridden (plugins, child theme, parent theme), how often, or by naming convention. With this mindset, I've written my theme to allow many functions to be short-circuited this way.

For comparison:

Pluggable Function Override

if ( !function_exists('xyz_print_name') ){
    function xyz_print_name($name){
        //Do stuff here
    }
}

Short-circuited Function Override

function xyz_print_name($name){
    $override = apply_filters('xyz_pre_print_name', null, $name); //Notice $name is a single parameter, so this works no problem. See below for issues with multiple parameters when I split it into first and last name.
    if ( isset($override) ){return;}

    //Do stuff here
}

I could override it like this:

add_filter('xyz_pre_print_name', '__return_empty_string');

Or I could rewrite it like this:

add_filter('xyz_pre_print_name', 'abc_print_name');
function abc_print_name($name){
    //Do my own stuff here
    return true;
}

This has been absolutely great until I ran into the issue that has been plaguing my for the last few months on and off...

I can easily override functions with no parameters or even a single one, but two or more parameters will through a monkey wrench into everything.

I can't quite figure out why, either. I think it has something to do with the second parameter of apply_filters() itself: $value

Since I'm not passing a value, I assign it false, and use the actual $arg1, $arg2, etc. parameters. However, when I write the actual override function, I need to include a null value in the declaration to accommodate it. I feel like this is sloppy code:

add_filter('xyz_pre_print_name', 'abc_print_name', 10, 3); //I must pass 3 parameters here (instead of the 2 I need to account for the extra $null parameter)
function abc_print_name($null, $first_name, $last_name){ //Notice here I need to pass $null as the first parameter
    //Do stuff here
}

Instead, I could do it like this, but I've noticed it breaks some of my functions (and technically is incorrect according to the WordPress Codex since I'm misusing the $value parameter):

//...
$override = apply_filters('xyz_pre_print_name', $first_name, $last_name);
//...

add_filter('xyz_pre_print_name', 'abc_print_name', 10, 2);
function abc_print_name($first_name, $last_name){ //Notice $first_name is being passed as the $value parameter of the filter- which is wrong
    //Do my own stuff here
}

One last quick note, if I switch my override to use do_action() instead of apply_filter() which does not have the extra parameter before the arguments, everything works great again except that I can not detect if the override hook was used, so both the override function and then my original function run.

Phew, that's a long question. TL;DR Is anyone else short-circuiting functions in WordPress? I thought I saw some discussion about it even in WordPress core. If so, how are you doing it? Have you run into similar issues?

I struggle so much to find others trying this method, so I'd appreciate any insight at all. I just don't want to give up on this method...

Edit: To specify my question:

Is there a better way to allow for short-circuiting a function so that an extra $null parameter does not need to be used when utilizing it? I've also added comments in my above snippets for what I'm specifying in each.

有帮助吗?

解决方案

First, please avoid doing echo on filters. Cause filter are not designed the way to handle echo. They are designed to take a parameter or input and modify or manipulated inside the hooked function and send it back to the parent function. If this filters don't return data then there is a huge chance to get broke the WordPress life cycle.

Secondly, there is a significant difference between do_action and apply_filters. do_action does define a flag where you can add some functions to execute. It's kinda putting some extra functions in that point to execute. Where what apply_filters does is to define a flag from where you can get some data, then modify or manipulate it then return it to the parent. This way you can manipulate the data.

Lastly come to your point on use the $null value. Well, if you read the apply_filters documentation then you can see that the first parameter is the values which we need to modify and the other variables are the additional parameters or arguments. So for modifying the value first you need to get the value inside the function. And as it is required, so you can't escape it. And also you can't break the order of the value and arguments when inputting them to the hooked function cause it takes the input value and argument as the order, not as the name.

Hope that above helps.

许可以下: CC-BY-SA归因
scroll top