7

When developing themes and plugins it is sometimes neccesary to add some functionality to some hook using conditional statements.

Example:

function my_custom_function() {
    if( is_home()) {
       <---what should the function do--->
    }
}

 add_action( 'some_hook', 'my_custom_function' );

To my understanding, whenever any other condition exists (is_home return false), the content of the function is not executed, however the function is executed, although it is "empty". This means that an empty function is passed to the hook. This is the way that all examples are shown in the codex using conditional tags.

I do understand that this is safe to do so, and it should not have any significant impact on load times (if there is any impact on load time at all).

I have been thinking, the same piece of code, as per example, can be written as follow

if( is_home()) {
   function my_custom_function() {
     <---what the function should do--->
   }

  add_action( 'some_hook', 'my_custom_funtion' );

}

This will completely skip everything if is_home returns false.

I don't mind using any of these two methods. But what I want to know, because of the first example been extensively used, are there any coding standard that states that this is the correct method to use, or is this rather the prevered way according to wordpress developers, or just personal preference.

5 Answers 5

8

WordPress coding standards for PHP does not state anything about this, and there is no other standard, so it's up to developers to choose one way or another.

I have to say that the 2 methods have different approaches; while the first contains conditional logic, the second is a conditional function declaration, which means that if you try to call the function, you obtain a fatal error.

Even if using the first method, where the function runs (with a very minimal impact on performance that is irrelevant and lost in the application load), it is a better approach to use it, because when using the second method, the business logic of your application is moved from functions to the file parsing.

Moreover, you should consider there is a third way you've not mentioned:

function my_custom_function() {
    // what the function should do
}

if ( is_home() ) {
    add_action( 'some_hook', 'my_custom_function' );
}

The benefit to this approach is more perceptible when you use OOP programming: in that case, class conditional declaring makes no sense (and method conditional declaring is not possible at all), but it makes a lot of sense running tasks only under specific conditions (hooks firing).

1
  • It was tough deciding between you and @toscho, but I have to give it to you for linking to the wordpress standards. Thanks for a great answer Commented May 26, 2014 at 9:32
8

Do not create functions on the fly. This is hard to read and to debug. Implement separation of concerns instead, and separate the registration of callbacks from their execution (business logic). Setting the conditional checks logically in front of the callback registration is dead simple now.
Wait for the action template_redirect to instantiate that registration handler, because that’s when you know if is_home() can be checked.

Example

class Theme_Hooks
{ 
    public function setup()
    {
        if ( ! is_404() ) {
            add_action(
                get_stylesheet() . '_breadcrumb',
                [ new Breadcrumb, 'render' ]
            );
        }

        if ( is_home() ) {
            add_action(
                get_stylesheet() . '_home_widget',
                [ new Home_Widget, 'render' ]
            );
        }
    }
}

add_action( 'template_redirect', [ new Theme_Hooks, 'setup' ] );
2
  • Makes perfect sense. +1 Commented May 26, 2014 at 9:28
  • It would have been good to mention that you shouldn't be calling is_home() that early anyway, or you'll get this: PHP Notice: is_home was called <strong>incorrectly</strong>. Conditional query tags do not work before the query is run. Before then, they always return false. Please see <a href="http://codex.wordpress.org/Debugging_in_WordPress">Debugging in WordPress</a> for more information. (This message was added in version 3.1.).
    – J.D.
    Commented May 26, 2014 at 15:50
4

I just want to add that in general, one should be careful using conditional tags like:

if( is_*() )
{
    // stuff
}

in the global scope of functions.php, because it will run before any filter or action is fired with do_action() or apply_filters().

0
0

I'd say personal preference.

Additionally it is cleaner to take the function call outside the if-statement, and the action inside it. That way the function will still only be called by the action if the if-statement returns true.

Always keeping function definitions outside the if-statement ensures that you'll never end up calling a function that happens to be trapped and uncallable.

0

Just want to add another option. Hybrid Core framework has implemented a method called "smarter hooks" which recognize the context.

The full source can be looked here:

https://github.com/justintadlock/hybrid-core/blob/master/functions/core.php

Ideally, it can be used like this:

An example of a basic hook would be 'hybrid_header'. The do_atomic() function extends that to give extra hooks such as 'hybrid_singular_header', 'hybrid_singular-post_header', and 'hybrid_singular-post-ID_header'.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.