So I have created this widget which pulls a number of posts. And the query is being cached via transients. But I need the transient to be deleted whenever a post is saved so the query can be refreshed.

Have a look at this code snippet.

add_action( 'save_post', 'delete_transient' );

function delete_transient() {
     if ( $_POST['post_type'] === 'post' ) {
          // this is a hack around to delete widget transients
          $max = 20;

          for( $i = 1; $i <= $max; $i++ ) { 
           delete_transient( 'my-posts-widget-' . $i );
          }          
     }
}

Ok so everything setup and working however because a widget can have multiple instances, deleting the transient is becoming an issue. Here is why. Every time you put a widget into the sidebar, the unique number WP assigns is incremented. So if someone happened to drag the widget out and then put it back again, it will increment the number again. So my $max = 20 will soon not be valid anymore as the id could then be 30… I could set the $max to 100000+ but that is not practical.

So with that in mind, you can see this is not a fully working solution. So my question is how are you guys handling this or have an idea of a work around?

Thanks for looking.

2 Answers
2

Use a widget cache and forget the actual number of active widgets.

In your widget add this to your method widget():

public function widget( $args, $instance ) 
{
    // get the cache
    $cache = wp_cache_get( 'UNIQUE_WIDGET_IDENTIFIER', 'widget' );

    if ( !is_array( $cache ) )
        $cache = array();

    if ( ! isset ( $args['widget_id'] ) )
        $args['widget_id'] = $this->id;

    if ( isset ( $cache[ $args['widget_id'] ] ) )
        return print $cache[ $args['widget_id'] ];

    // go on with your widget logic, put everything into a string and …

    $cache[ $args['widget_id'] ] = $widget_string;

    wp_cache_set( 'UNIQUE_WIDGET_IDENTIFIER', $cache, 'widget' );

    print $widget_string;
}

And in your widget’s __construct() register the flush actions:

add_action( 'save_post',    array( $this, 'flush_widget_cache' ) );
add_action( 'deleted_post', array( $this, 'flush_widget_cache' ) );
add_action( 'switch_theme', array( $this, 'flush_widget_cache' ) );

The callback in your widget class is just a simple …

public function flush_widget_cache() 
{
    wp_cache_delete( 'UNIQUE_WIDGET_IDENTIFIER', 'widget' );
}

Transients time out even if nothing has changed. That’s not what you need here.
Don’t forget to replace UNIQUE_WIDGET_IDENTIFIER with your own value. 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *