1

I'd like to call a function Y($arg) when the hook X is fired.

Alternative: catch the return value from function Y(), which is called via add_action('X', 'Y'); in function W, which contains the add_action() statement.

How do I do that?

My use case:

I have a function createMainPanel() that returns a string $ret to be displayed.

I only have access to the post meta info after the "template_redirect" hook, e.g. get_post() and the like only have sensible values after that hook. Thus, I want to add an add_action('redirect_template', retrievePostInfo') with the currently prepared string for output ($ret)) and let that function build the rest and print the page with echo.

An alternative thought was somehow to retrieve the return of retrievePostInfo() and append it to the string of createMainPanel().

However, I can't see a working way to implement either of these possibilities.

EDIT

I solved my problem in a way unrelated to the question, but here's the code:

ERRONEOUS CODE:

function showPostMetaInfo()
{
    $id = get_the_ID();

    $string.= "<table id='meta-info'>"
            . "<thead>"
            . "<tr>"
            . "<th> Meta Type </th>"
            . "<th> Value"
            . "</tr>"
            . "</thead>"
            . "<tbody>"
            . "<tr>"
            . "<td> Title </td>"
            . "<td>".get_the_title($id)."</td>"
            . "</tr>"
            . "<tr>"
            . "<td> Author </td>"
            . "<td>".get_the_author($id)."</td>"
            . "</tr>"
            . "<tr>"
            . "<td> Published </td>"
            . "<td>".get_the_date("", $id)."</td>"
            . "</tr>"
            . "<tr>"
            . "<td> Last Modified </td>"
            . "<td>".get_the_modified_date("", $id)."</td>"
            . "</tr>"
            . "<tr>"
            . "<td> Categories </td>"
            . "<td>".listCategories($id)."</td>"
            . "</tr>"
            . "<tr>"
            . "<td> Tags </td>"
            . "<td>".listTags($id)."</td>"
            . "</tr>"
            . "</tbody>"
            . "</table>";

    return $string;
}

CORRECT CODE:

function showPostMetaInfo()
{
    $id = get_queried_object_id();

    $string.= "<table id='meta-info'>"
            . "<thead>"
            . "<tr>"
            . "<th> Meta Type </th>"
            . "<th> Value"
            . "</tr>"
            . "</thead>"
            . "<tbody>"
            . "<tr>"
            . "<td> Title </td>"
            . "<td>".get_the_title($id)."</td>"
            . "</tr>"
            . "<tr>"
            . "<td> Author </td>"
            . "<td>".get_the_author($id)."</td>"
            . "</tr>"
            . "<tr>"
            . "<td> Published </td>"
            . "<td>".get_the_date("", $id)."</td>"
            . "</tr>"
            . "<tr>"
            . "<td> Last Modified </td>"
            . "<td>".get_the_modified_date("", $id)."</td>"
            . "</tr>"
            . "<tr>"
            . "<td> Categories </td>"
            . "<td>".listCategories($id)."</td>"
            . "</tr>"
            . "<tr>"
            . "<td> Tags </td>"
            . "<td>".listTags($id)."</td>"
            . "</tr>"
            . "</tbody>"
            . "</table>";

    return $string;
}
  • It sounds like you're trying to alter page/post content before it gets displayed. Is there a reason you're not using the the_content filter? – Pat J Nov 5 '16 at 21:14
  • @PatJ Almost. I want to alter the sidebar content to show post meta information, rather than appending it to the post... here is a screenshot: i.imgur.com/tWVw46b.png – Alex Nov 5 '16 at 21:48
  • Can you please edit your question to show the code you're using to create your meta panel? – Pat J Nov 5 '16 at 22:27
  • @PatJ I have solved my problem in a way unrelated to the question, nevertheless, I'll post the erroneous and the corrected code. – Alex Nov 5 '16 at 22:57
1

It's possible to use functions in a way that allow for one action to pass variables to the next. In this case, I've waited till the wp_head event to add the_content filter. And it will be using the queried_object_id when appending content with showPostMetaInfo.

This makes your function a little more OOP friendly.

// Wait till the head
add_action( 'wp_head', function() {

    // Get the queried ID for use with `the_content`
    $queried_id = get_queried_object_id();

    add_filter( 'the_content', function( $content ) use ( $queried_id ) {

        // append post meta info to content
        return $content . showPostMetaInfo( $queried_id );
    } );
} );

function showPostMetaInfo( $id = null ) {

    if ( empty( $id ) ) {
        return '';
    }

    ob_start();

    ?>
    <table id='meta-info'>
    <thead>
    <tr>
        <th> Meta Type</th>
        <th> Value
    </tr>
    </thead>
    <tbody>
    <tr>
        <td> Title</td>
        <td><?php echo get_the_title( $id ); ?></td>
    </tr>
    <tr>
        <td> Author</td>
        <td><?php echo get_the_author( $id ); ?></td>
    </tr>
    <tr>
        <td> Published</td>
        <td><?php echo get_the_date( "", $id ); ?></td>
    </tr>
    <tr>
        <td> Last Modified</td>
        <td><?php echo get_the_modified_date( "", $id ); ?></td>
    </tr>
    <tr>
        <td> Categories</td>
        <td><?php echo listCategories( $id ); ?></td>
    </tr>
    <tr>
        <td> Tags</td>
        <td><?php echo listTags( $id ); ?></td>
    </tr>
    </tbody>
    </table><?php

    return ob_get_clean();
}

function listCategories( $id ) { return 'listCategories: ' . $id; };
function listTags( $id ) { return 'listTags: ' . $id; };

Note: This won't work with all versions of PHP.


Option 2

Taking this a step further, you could create a class that allows for dynamic data (including methods) and route your functions through it using magic methods.

if ( ! class_exists( 'FunctionProxy' ) ):

    class FunctionProxy {

        private $s = array ();

        // properties
        function __set( $k, $c ) { $this->s[ $k ] = $c; }
        function __get( $k ) { return isset($this->s[ $k ]) ? $this->s[ $k ] : null; }

        // methods
        public function __call( $method, $args ) {
            if ( isset($this->s[ $method ]) && is_callable( $this->s[ $method ] ) ) {
                return call_user_func_array( $this->s[ $method ], func_get_args() );
            } else {
                echo "unknown method " . $method;
                return false;
            }
        }

        // backtrace caller
        static function get_backtrace_object( $depth = 3 ) {
            $trace  = debug_backtrace();
            return isset( $trace[ $depth ][ 'object' ] ) ? $trace[ $depth ][ 'object' ] : null;
        }
    }

endif;

Using the FunctionProxy dynamic object you can make methods and properties on the fly.

// Wait till the head
add_action( 'wp_head', function() {

    // create our dynamic object
    $func = new FunctionProxy();

    // Get the queried ID for use with `the_content`
    $func->queried_id = get_queried_object_id();

    // Create a method on the object
    $func->filter_the_content = function( $content ) {

        // Find the callee of this function
        $caller = FunctionProxy::get_backtrace_object();

        // Return content plus post meta from our caller object
        return $content . showPostMetaInfo( $caller->queried_id );
    };

    // add content filer
    add_filter( 'the_content', array ( $func, 'filter_the_content' ) );
} );

Reference

0

You can't get anything back from add_action() -- it always returns true.

Reference

  • Thanks for this. Is it, however, possible to pass an argument to the callee function called by add_action( string $tag, callable $function_to_add, int $priority = 10, int $accepted_args = 1) ? – Alex Nov 5 '16 at 23:06
  • Absolutely. The number of arguments you can pass depends on the action. In the documentation for the various hooks, you can see the accepted arguments (if any) after the name of the action hook. For example, template_redirect takes no arguments; updated_postmeta accepts 4. – Pat J Nov 6 '16 at 16:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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