如何在更新小工具的值时重置瞬变?

时间:2018-02-16 作者:Jonathan Guerin

我有一个Instagram小部件,它使用Instagram刮刀,根据自定义程序输入的用户名,在瞬间缓存数据以显示照片。

不幸的是,当我更新用户名时,瞬态不会更新。它使用旧的(来自旧用户名),这实际上不允许我使用新用户名渲染照片,这使得小部件在第一次使用后有些无用。

简言之,我正在寻找类似的东西:

if( is_updated($username) ? new_transient($username) : get_transient($username).

scrapper[skip to next block for the transient bit]:

<?php

namespace Social_Space;

/**
 * Interface to scrape most popular JSON-enabled social networks.
 */
interface Scrape_Interface {

    /* Builds the end-point, or the link that will be queried */
    public function build_endpoint();

    /* Ingests the pure, non-altered JSON data */
    public function get_json();

    /* Handles and cleans the data */
    public function get_data();
}

class Scrape_Instagram implements Scrape_Interface {

    private $username;

    public function set_username( $username ) {
        $this->username = $username;
    }

    /**
     * Builds the endpoint for the Instagram API, provided the username from constructor.
     * @param $end_cursor   Used in case the user wants more pictures to be scrapped.
     */
    public function build_endpoint() {
        return \'https://www.instagram.com/\' . trim( strtolower( $this->username ) ) . \'/?__a=1\';
    }

    /**
     * GETs the data from Instagram, provided the endpoint.
     */
    public function get_json() {
        if ( false === ( $data = get_transient( \'instagram_data\' ) ) )  {
            $request = wp_remote_get( $this->build_endpoint() );

            if( is_wp_error( $request ) ) {
                return new WP_Error( \'site-down\', esc_html__( \'Instagram may be down. Unable to communicate.\', \'_s\') );
            }

            elseif( wp_remote_retrieve_response_code( $request ) !== 200 ) {
                return new WP_Error( \'invalid-response\', esc_html__( \'Got an invalid response.\', \'_s\') );
            }

            else {
                set_transient( \'instagram_data\', wp_remote_retrieve_body( $request ), 5 );
            }
        }
        return $data;
    }

    /**
     * Ingests the data from get_json() then converts / decodes into an array.
     */
    public function get_data() {
        $json = $this->get_json();

        if( is_wp_error( $json ) ) {
            return new WP_Error( \'invalid-json\', esc_html__( \'Something is wrong. Did you enter the right username?\', \'_s\' ) );
        }

        $data = json_decode( $json, true);

        if( is_wp_error( $data ) ) {
            return new WP_Error( \'invalid-data\', esc_html__( \'Something is wrong. Did you enter the right username?\', \'_s\' ) );
        } else {
            return $data;
        }
    }
}

class Generate_Instagram_Links {

    private $instagram_object;
    private $username;

    public function __construct( $username, Scrape_Instagram $instagram_object = null ) {
        $this->username = $username;
        $this->instagram_object = $instagram_object === null ? new Scrape_Instagram : $instagram_object;
        $this->instagram_object->set_username( $this->username );
    }

    /**
     * Generates the link to the source image, as well as to the instagram post of each image
     * requested by our script.
     */
    public function get_links() {
        $response = $this->instagram_object->get_data();
        /**
         * Based on the array generated from get_data(), some nodes have resulted that contain    * information about
         * each photo the user has, as such, we\'ll loop through each photo and access any data.
         * @see [\'user\'][\'media\'][\'nodes\'] - individual node / image.
         */
        if( is_wp_error( $response ) ) {
            return new WP_Error( \'invalid-json\', esc_html__( \'Ouch. The data was not parsed correctly. Cannot continue.\' ) );
        } else {
            foreach( $response[\'user\'][\'media\'][\'nodes\'] as $node ) {
                $image = array(\'real_link\' => \'src\' );
                $image[\'real_link\'] = \'https://www.instagram.com/p/\' . $node[\'code\'] . \'?taken-by=\' . $this->username;
                $image[\'src\'] = $node[\'thumbnail_resources\'][0][\'src\'];
                $images_links[] = $image;
            }
        }
        return $images_links;
    }

    /**
     * Getter for the instagram links (non-local).
     */
    public function get_instagram_photos_links() {
        $links = $this->get_links();

        if( is_wp_error( $links) ) {
            return new WP_error( \'unknown-error\', esc_html__( \'Something went wrong. Cannot get data. Check username or contact developer.\') );
        } else {
            return $links;
        }
    }

    /**
     * Gets the local photo links of the newly added instagram photo links, or retrieves the
     * links if they already exist(to not flood the media library).
     * @todo        Add an "expiry" date for each image, or remove if no longer used.
     */
    private function get_local_links() {
        // Requires loading of the wp-admin scripts.
        require_once (\'wp-load.php\');
        require_once (\'wp-admin/includes/admin.php\');

        $urls = $this->get_instagram_photos_links();

        $local_images   = array();

        foreach( $urls as $url ) {

            $tmp = download_url( $url[\'src\'] );

            $file_array = array(
                \'name\'      => basename( $url[\'src\'] ),
                \'tmp_name\'   => $tmp
            );

            $wp_upload_dir = wp_get_upload_dir();
            $local_url = $wp_upload_dir[\'path\'] . \'/\' . $file_array[\'name\'];

            if( file_exists( $local_url ) ) {
                array_push( $local_images, ($wp_upload_dir[\'url\'] . \'/\' . $file_array[\'name\']) );
            } else {
                if ( is_wp_error( $tmp ) ) {
                    @unlink( $file_array[ \'tmp_name\' ] );
                    return $tmp;
                }

                $GLOBALS[\'post\'] = null;

                $post_id = \'0\';

                $id = media_handle_sideload( $file_array, $post_id, $desc = null, $post_data = array(\'post_content\' => \'insta_image\' ) );

                if ( is_wp_error( $id ) ) {
                    @unlink( $file_array[\'tmp_name\'] );
                    return $id;
                }

                $value = wp_get_attachment_url( $id );

                array_push( $local_images, $value );
            }
        }
        return $local_images;
    }

    /**
     * Getter for the instagram links (local).
     */
    public function get_instagram_local_photos_links() {
        $links = $this->get_local_links();

        if( is_wp_error( $links) ) {
            return new WP_error( \'unknown-error\', esc_html__( \'I cannot get the local links of the pictures. Check with the developer.\' ) );
        } else {
            return $links;
        }
    }
}

namely the function "get_json":

public function get_json() {
    if ( false === ( $data = get_transient( \'instagram_data\' ) ) )  {
        $request = wp_remote_get( $this->build_endpoint() );

        if( is_wp_error( $request ) ) {
            return new WP_Error( \'site-down\', esc_html__( \'Instagram may be down. Unable to communicate.\', \'_s\') );
        }

        elseif( wp_remote_retrieve_response_code( $request ) !== 200 ) {
            return new WP_Error( \'invalid-response\', esc_html__( \'Got an invalid response.\', \'_s\') );
        }

        else {
            set_transient( \'instagram_data\', wp_remote_retrieve_body( $request ), 5 );
        }
    }
    return $data;
}
如上所述,这行不通。这是我的小部件,我在其中检查$username 在做任何事情之前widget() 作用

<?php
/**
 * Plugin Name: Instagram Widget
 */


add_action( \'widget_init\', \'custom_widget_instagram_pictures\');
register_widget( \'custom_widget_instagram_pictures\' );

class custom_widget_instagram_pictures extends Wp_Widget {

    /**
     * Setup the Widget
     */
    public function __construct() {
        $widget_ops = array(\'classname\'     => \'custom_widget_instagram_pictures\',
                            \'description\'   => esc_html__(\'A widget to display instagram photos.\', \'_s\')
                            );

        $control_ops = array(\'id_base\'      => \'custom_widget_instagram_pictures\');

        parent::__construct( \'custom_widget_instagram_pictures\', __(\'_s: Instagram Widget\', \'_s_instagram_widget\'), $widget_ops, $control_ops );
    }

    public function widget( $args, $instance ) {
        extract( $args );
        $title              = isset( $instance[\'title\'] ) ? apply_filters(\'widget_title\', $instance[\'title\'] ) : \'\';
        $username           = isset( $instance[\'username\'] ) ? $instance[\'username\'] : \'\';
        $profile_link       = isset( $instance[\'profile_link\'] ) ? $instance[\'profile_link\'] : \'\';
        $columns            = isset( $instance[\'columns\'] ) ? $instance[ \'columns\'] : \'\';
        $save_local         = isset( $instance[\'save_local\'] ) ? $instance[\'save_local\'] : \'\';
        $number_of_photos   = isset( $instance[\'number_of_photos\'] ) ? $instance[\'number_of_photos\'] : \'\';

        echo ent2ncr( $before_widget );

        if ( $title ) {
            echo ent2ncr( $before_title . $title . $after_title );
        }
        ?>
        <div class="instagram-widget">
                <?php
                if( $username ) {
                    $instagram_object = new Social_Space\\Generate_Instagram_Links( $username, new Social_Space\\Scrape_Instagram );

                    if ( !$save_local ) {

                        $instagram_links = $instagram_object->get_instagram_photos_links();

                        if( is_wp_error( $instagram_links ) ) {
                            echo "Ouch. Something\'s wrong. Did you enter the right username?";
                        } else {

                            $instagram_links_parsed = 0;
                            ?>
                            <ul class="instagram-widget-list">
                            <?php
                                foreach( $instagram_links as $link ) {
                                    if ( $instagram_links_parsed < absint( $number_of_photos ) ) {
                                        $instagram_links_parsed++;
                                        ?>
                                        <li class="instagram-thumb instagram-thumb-<?php echo $columns ?>-col">
                                            <a href="<?php echo $link[\'real_link\']; ?>"><img src="<?php echo $link[\'src\']; ?>"/></a>
                                        </li>
                                        <?php
                                    }
                                    else {
                                        break;
                                    }
                                }
                            ?>
                            </ul>
                            <?php
                        }
                    }

                    elseif ( $save_local ) {

                        $instagram_links = $instagram_object->get_instagram_local_photos_links();

                        if( is_wp_error( $instagram_links ) ) {
                            echo "Ouch. Something\'s wrong. Did you enter the right username?";
                        } else {
                            $instagram_links_parsed = 0;

                            ?>

                            <ul class="instagram-widget-list">
                            <?php
                                foreach( $instagram_links as $link ) {
                                    if ( $instagram_links_parsed < absint( $number_of_photos ) ) {
                                        $instagram_links_parsed++;
                                        ?>
                                        <li class="instagram-thumb instagram-thumb-<?php echo $columns ?>-col">
                                            <a href="<?php echo $link; ?>"><img src="<?php echo $link; ?>"/></a>
                                        </li>
                                    <?php
                                    }
                                    else {
                                        break;
                                    }
                                }
                            ?>
                            </ul>
                            <?php
                        }
                    }
                } else {
                    echo _s_setup_widget_notification();
                } ?>
            <?php if( \'on\' == $profile_link ) : ?>
            <button class="instagram-widget-profile-link"><a href="<?php echo \'https://www.instagram.com/\' . $username; ?>"><i class="sf-4"></i><p><?php echo $username ?></p></a></button>
            <?php endif; ?>
        </div>
        <?php
        echo ent2ncr( $after_widget );
    }

    function update( $new_instance, $old_instance ) {
        $instance[\'title\']          = ( isset( $new_instance[\'title\'] ) ) ? strip_tags($new_instance[\'title\'] ) : \'\';
        $instance[\'username\']       = ( isset( $new_instance[\'username\'] ) ) ? strip_tags( $new_instance[\'username\'] ) : \'\';
        $instance[\'profile_link\']   = ( isset( $new_instance[\'profile_link\'] ) ) ? strip_tags( $new_instance[\'profile_link\'] ) : \'\';
        $instance[\'columns\']        = ( isset( $new_instance[\'columns\'] ) ) ? strip_tags( $new_instance[\'columns\'] ) : \'\';
        $instance[\'save_local\']     = ( isset( $new_instance[\'save_local\'] ) ) ? strip_tags( $new_instance[\'save_local\'] ) : \'\';
        $instance[\'number_of_photos\'] = ( isset( $new_instance[\'number_of_photos\'] ) ) ? strip_tags( $new_instance[\'number_of_photos\'] ) : \'\';

        return $instance;
    }

    function form( $instance ) {
        $defaults = array(  \'title\'             => \'\',
                            \'username\'          => \'\',
                            \'profile_link\'      => \'\',
                            \'columns\'           => \'3\',
                            \'save_local\'        => \'\',
                            \'number_of_photos\'  => \'12\',
                        );

        $instance = wp_parse_args( (array) $instance, $defaults ); ?>

        <!-- Custom Message -->
        <div class="customizer-custom-message-1">
            <p>Hey! Just one second. We strongly advise you keep an "even" number of images, 3 columns should have 3,6,9...photos. A 2 columns layout should have 2,4,6 and so on. Looks much better this way! </p>
        </div>
        <!-- Form for Title -->
        <p>
            <label for="<?php echo $this->get_field_id( \'title\' ); ?>">Widget Title:<strong>(Leave Blank to Hide)</strong></label>
            <br>
            <input class="widefat" id="<?php echo $this->get_field_id( \'title\' ); ?>" name="<?php echo $this->get_field_name( \'title\' ); ?>" value="<?php echo $instance[\'title\'];?>" />
        </p>

        <!-- Form for Username -->
        <p>
            <label for="<?php echo $this->get_field_id( \'username\' ); ?>">Username:</label>
            <br>
            <input class="widefat" id="<?php echo $this->get_field_id( \'username\' ); ?>" name="<?php echo $this->get_field_name( \'username\' ); ?>" value="<?php echo $instance[\'username\'];?>" />
        </p>

        <!-- Checkbox for Local -->
        <p>
            <input class="checkbox" type="checkbox" <?php checked( $instance[ \'save_local\' ], \'on\' ); ?> id="<?php echo $this->get_field_id( \'save_local\' ); ?>" name="<?php echo $this->get_field_name( \'save_local\' ); ?>" />
            <label for="<?php echo $this->get_field_id( \'save_local\' ); ?>">Save Images to Local</label>
        </p>

        <!-- Checkbox for Profile Link -->
        <p>
            <input class="checkbox" type="checkbox" <?php checked( $instance[ \'profile_link\' ], \'on\' ); ?> id="<?php echo $this->get_field_id( \'profile_link\' ); ?>" name="<?php echo $this->get_field_name( \'profile_link\' ); ?>" />
            <label for="<?php echo $this->get_field_id( \'profile_link\' ); ?>">Show Instagram Button?</label>
        </p>

        <!-- Columns -->
        <p>
            <label for="<?php echo $this->get_field_id( \'columns\' ); ?>">How Many Columns to Display?<strong>(Leave Blank to Hide)</strong></label>
            <br>
            <input class="widefat" id="<?php echo $this->get_field_id( \'columns\' ); ?>" name="<?php echo $this->get_field_name( \'columns\' ); ?>" value="<?php echo $instance[\'columns\'];?>" />
        </p>

        <!-- Number of Photos -->
        <p>
            <label for="<?php echo $this->get_field_id( \'number_of_photos\' ); ?>">How Many Pictures?</label>
            <br>
            <input class="widefat" id="<?php echo $this->get_field_id( \'number_of_photos\' ); ?>" name="<?php echo $this->get_field_name( \'number_of_photos\' ); ?>" value="<?php echo $instance[\'number_of_photos\'];?>" />
        </p>
    <?php
    }
}

1 个回复
最合适的回答,由SO网友:Jacob Peattie 整理而成

最简单的方法就是在更新用户名时删除临时用户名。那么下次get_json() 运行时,将看到瞬态未设置,就像它已过期一样,然后检索数据并再次保存瞬态。

所以在update() 您可以执行以下操作:

if ( $new_instance[\'username\'] !== $old_instance[\'username\'] ) {
    delete_transient( \'instagram_data\' );
}
然而,设置瞬态的方式有一个问题,即只有一个瞬态,instagram_data, 无论您为哪个用户名获取数据,都会检索到该用户名。因此,即使您在更新小部件时删除瞬态,如果用户添加了多个具有不同用户名的小部件,瞬态也只会包含经过的第一个用户名的数据get_json().

您可以通过为每个用户创建瞬态来解决此问题。这只需要在您的get_json() 方法:

$transient_name = $this->username . \'_instagram_data\';

if ( false === ( $data = get_transient( $transient_name ) ) )  {
    // etc.
else {
    set_transient( $transient_name, wp_remote_retrieve_body( $request ), 5 );
}
小部件更新方法中的代码将变成:

if ( $new_instance[\'username\'] !== $old_instance[\'username\'] ) {
        delete_transient( $old_instance[\'username\'] . \'_instagram_data\' );
}
不过,这已经不再需要了,因为如果有一个新用户名,就会有一个新的瞬态,但这将有助于保持数据库不受任何不必要的瞬态的影响。

结束

相关推荐

Transients API and multisite

我们正在使用Atlas HTML站点地图插件,该插件使用transients API缓存站点地图,调用如下:set_transient( \'dmac_html_sitemap\', $output, 60*60*24*7 ); 现在,我们还有一个多站点设置,我想知道瞬态存储在哪里,WP multisite是否将它们分开。它将选项分开,因为每个站点(博客)都有自己的DB表前缀(例如wp\\U 29\\U选项)。我在某个地方读到,瞬态可以用memcached存储,所以我猜后端存储是可插入的。这个问