web-dev-qa-db-fra.com

Comment supprimer correctement les transitoires mis en cache d'une instance de widget?

Donc, j'ai créé ce widget qui tire un certain nombre de messages. Et la requête est mise en cache via des transitoires. Mais j'ai besoin que le transitoire soit supprimé à chaque fois qu'un message est enregistré pour que la requête puisse être actualisée.

Jetez un coup d'œil à cet extrait de code.

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, donc tout est configuré et fonctionne, mais comme un widget peut avoir plusieurs instances, la suppression du transitoire devient un problème. Voici pourquoi. Chaque fois que vous insérez un widget dans la barre latérale, le numéro unique attribué par WP est incrémenté. Donc, si quelqu'un tire le widget et le remet à sa place, il incrémentera à nouveau le nombre. Donc, mon $ max = 20 ne sera bientôt plus valide car l'id pourrait alors être 30 ... Je pourrais régler le maximum à 100000+ mais ce n'est pas pratique.

Donc, avec cela à l'esprit, vous pouvez voir que ce n'est pas une solution totalement opérationnelle. Ma question est donc la suivante: comment gérez-vous cela ou avez-vous une idée du problème?

Merci d'avoir regardé.

3
user23654

Utilisez un cache de widgets et oubliez le nombre réel de widgets actifs.

Dans votre widget, ajoutez ceci à votre méthode 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;
}

Et dans la fonction __construct() de votre widget, enregistrez les actions de vidage:

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' ) );

Le rappel dans votre classe de widgets n’est qu’un simple…

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

Les transitoires expirent même si rien n'a changé. Ce n'est pas ce dont vous avez besoin ici.
N'oubliez pas de remplacer UNIQUE_WIDGET_IDENTIFIER par votre propre valeur. :)

2
fuxia

Donc, je suis venu avec ce travail hacky autour pour le moment mais ça marche.

add_action( 'save_post', 'delete_transient' );

function delete_transient() {
     if ( $_POST['post_type'] === 'post' ) {
          $ids = get_widget_id_number();

          foreach( $ids as $id ) { 
              delete_transient( 'my-posts-widget-' . $id );
          }          
     }
}

function get_widget_id_number() {
    $widgets = get_option( 'sidebars_widgets' );
    $widget_ids = array();

    foreach( $widgets as $widget ) {
        if ( is_array( $widget ) ) {
            foreach( $widget as $widget_saved ) {
                $widget_saved_name = substr( $widget_saved, 0, strrpos( $widget_saved, '-' ) );
                $widget_id = substr( $widget_saved, -1, strrpos( $widget_saved, '-' ) );
                if ( $widget_saved_name === 'my-posts-widget' )
                    $widget_ids[] = $widget_id;
            }
        }
    }

    array_unique( $widget_ids );

    return $widget_ids;
}

J'espère que cela aidera les autres dans cette situation.

1
user23654