Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

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.

share|improve this question

5 Answers 5

up vote 8 down vote accepted

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

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

Even if using the first method the function run (with a very minimal impact on performance that is irrelevant and lost in the application load), it is a better approach use it, because 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 not mentioned:

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

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

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

share|improve this answer
    
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 –  Pieter Goosen May 26 at 9:32

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' ] );
share|improve this answer
    
Makes perfect sense. +1 –  Pieter Goosen May 26 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. May 26 at 15:50

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().

share|improve this answer
    
Thank you for adding this info. +1 –  Pieter Goosen May 26 at 9:29

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.

share|improve this answer

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'.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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