Shared functionality in plugins and themes

I recently started to develop plugins and themes and I found that I need to use several functions of on both.

Sometime I think about to check if function / class exist before declared as said on this post: When to check if a function exists

Read More

But that is considered as bad practice. What is best practice to prevent conflicts and keep themes & plugin work independently without one themes / plugin installed?

Related posts

Leave a Reply

1 comment

  1. Actions & Filters

    The imho best way is to use an action to bring plugin functions into themes.

    Example #1

    Here’s a little plugin to test this.

    <?php 
    /** Plugin Name: (#68117) Print Hello! */
    function wpse68117_print_hello()
    {
        echo "Hello World!";
    }
    add_action( 'wpse68117_say', 'wpse68117_print_hello' );
    

    Inside the theme:

    <?php
    /** Template Name: Test »Print Hello!« Plugin */
    get_header();
    // Now we call the plugins hook
    do_action( 'wpse68117_say' );
    

    What now happens / The kool kid

    This way we don’t have to check the existence of a function, a file, a class, a method or maybe even a (don’t do this!) global $variable. The WP intern global already takes this for us: It checks if the hook name is the current filter and attaches it. If it doesn’t exists, nothing happens.

    Example #2

    With our next plugin, we’re attaching a callback function that takes one argument.

    <?php 
    /** Plugin Name: (#68117) Print Thing! */
    function wpse68117_print_thing_cb( $thing )
    {
        return "Hello {$thing}!";
    }
    add_filter( 'wpse68117_say_thing', 'wpse68117_print_thing_cb' );
    

    Inside the theme:

    <?php
    /** Template Name: Test »Print Thing!« Plugin */
    get_header();
    // Now we call the plugins hook
    echo apply_filter( 'wpse68117_say_thing', 'World' );
    

    This time, we offer the user/developer the possibility to add an argument. He can either echo/print the output, or even process it further (in case you got an array in return).

    Example #3

    With the third plugin, we’re attaching a callback function that takes two arguments.

    <?php 
    /** Plugin Name: (#68117) Print Alot! */
    function wpse68117_alot_cb( $thing, $belongs = 'is mine' )
    {
        return "Hello! The {$thing} {$belongs}";
    }
    add_filter( 'wpse68117_grab_it', 'wpse68117_alot_cb' );
    

    Inside the theme:

    <?php
    /** Template Name: Test »Print Alot!« Plugin */
    get_header();
    // Now we call the plugins hook
    $string_arr = implode(
         " "
        ,apply_filter( 'wpse68117_grab_it', 'World', 'is yours' )
    );
    foreach ( $string_arr as $part )
    {
         // Highlight the $thing
         if ( strstr( 'World', $part ) 
         {
             echo "<mark>{$part} </mark>";
             continue;
         }
         echo "{$part} ";
    }
    

    This plugin now allows us to insert two arguments. We can save it into a $variable and further process it.

    Conclusion

    With using filters and actions you’re giving better performance by avoiding unnecessary checks (compare speed of function_*/class_*/method_*/file_exists or the search for a global with in_array() for ~1k(?) filter searches). You also avoid having all those unnecessary Notices for not set variables, etc., as the plugin cares about this.