iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 7
1
自我挑戰組

Wordpress 外掛開發系列 第 7

「Wordpress 外掛開發」效能調整 Cache Api/Transient API

安全後,在意一下效能

在WP中提供兩個快取資料來讓時間保有時間有效性,Cache APITransient API,這些其實與ROR或者是Laravel如出一徹,只是後者比較特別一點,是使用我們admin中講到的Options API改裝而成的,只不過他也是會隨著時間過期的。

Cache API

快取的概念大家都了解,是現在保存資料後給之後使用,不過Wordpress只提供有時效性的快取,也因此你可以設定很多次的快取,讓你資料庫少些直接存取的問題;而wp提供了三個方式可以來做操作,與JS的cookie有異曲同工之妙,有興趣可以參考這一篇講cookie

// 設定快取資料
wp_cache_add( int|string $key, mixed $data, string $group = '', int $expire = 0 );
// 取代已經存在的資料
wp_cache_replace( int|string $key, mixed $data, string $group = '', int $expire = 0 );
// 這個是兩者的綜合體,大部分我們用這個來做
wp_cache_set( int|string $key, mixed $data, string $group = '', int $expire = 0 );

我們來時做一個有快取功能的頁面吧!目標是將recently的資料放進快取並且顯示,我們會預設他們開起在一個單獨的Post之中,然後試著被我們先儲存過的快取資料來當相關資料的基底,而如果沒有快取資料,則發一個新的post然後快取他們,最後再我們取得的資料列印在html上。

我們在判斷是否是獨一的post,可以使用is_single或是is_singular('post')來做判斷,不過在Wordpress的開發書上也有看到不同的判斷方式,是利用in_the_loop的方式,也是可行的。

add_filter( 'the_content', 'gogo_power_ranger_related_posts' );
 
function gogo_power_ranger_related_posts( $content ) {
 
  if ( is_single() && 'post' == get_post_type() )  {
        return $content;
  }

  $post_id = get_the_ID();
// 我們在這取快取
  $posts = wp_cache_get( $post_id, 'gogo_power_ranger_related_posts' );

  // 來這裡判斷是否有快取資料
  if ( ! $posts ) {
    // 沒有就存         
    $categories = get_the_category();
    $posts = get_posts( [
          'category' => absint( $categories[0]->term_id ),
          'post__not_in' => [ $post_id ],
          'numberposts'  => 5
    ] );

    if ( $posts ) {
          wp_cache_set(
                  $post_id,
                  $posts,
                  'gogo_power_ranger_related_posts',
                  DAY_IN_SECONDS
          );
    }
  } else {
      $content .= '<h3>相關內容</h3>';
      $content .= '<ul>';
      foreach ( $posts as $post ) {
            $content .= sprintf(
                    '<li><a href="%s">%s</a></li>',
                    esc_url( get_permalink( $post->ID ) ),
                    esc_html( get_the_title( $post->ID ) )
            );
      }
      $content .= '</ul>';
  }
  return $content;
}

Transients API

而接下來的這個,老實我很少使用這項功能,可以說不是很熟悉它來tune 效能,如果你的資料庫需要一個過一天就會消失的型態,那麼transients就是你需要的,如果你有去接經委會的即是報價API(假如他有也可以申請的到),則我們可以利用這個功能來做儲存並且有一定的時效性來驗證裡頭資料是否正卻,才不會被人以為是攻擊直接被ban了。

而在其他的外掛備啟動時,Transients很有可能會被轉去使用快取,也就是轉到去Cache API來事件這幾個程式碼了,所以你不想讓你的記憶體沒了造成資料庫還得重新開機的話,請好好設定時效何時該結束,而這邊我們也提到大神Ryan McCue對於這個的解釋

Everyone seems to misunderstand how transient expiration works, so the long and short of it is: transient expiration times are a maximum time. There is no minimum age. Transients might disappear one second after you set them, or 24 hours, but they will never be around after the expiration time.

好了我們來使用儲存、取得與刪除,分別是set_transientget_transientdelete_transient,而照慣例我們也來做一個簡單的transients應用,來獲取網路上的資料,假設我們是取得某個id的最近tweet,不過我不會真的去接,這邊需要你自己發揮了。


function gogo_power_ranger_fetch_tweet_by_id($ID) {
       return get_tweet($ID);
}
 
// Returns the video title.
function gogo_power_ranger_get_video_title($ID) {
 
       $tweet = get_transient( 'gogo_power_ranger_latest_tweet_'.$ID );
       if ( ! $tweet ) {
             $tweet = gogo_power_ranger_fetch_tweet_by_id($ID);
             set_transient( 'gogo_power_ranger_latest_tweet_'.$ID, $tweet, DAY_IN_SECONDS );
       }
       return $tweet;
}

初步已經完成,我們之後該怎麼擴增呢?

總概而言,網路上大家會比較推薦Transient來取代快取,畢竟不是每個資料都需要那麼即時,不過最重要的是挑選正確的使用型態,如果你要顯示這幾年很火紅的虛擬貨幣,兌換的匯率放進Transient會是個好的選擇來確保短的時程變化的正確性,以及極短時間不會有太多請求出去,而你也可以將有hashtag的Instagram加進自己的transient,這個片段是可以設計的長一點,對於需要做接到Http取回的資料,都是建議使用這個來做處理,而其餘的靜態資料與檔案,就交給cache來做吧。

最後,為何效能之前是安全性呢?其實有很多方式是可以去使用,我們中間有提到的不只是輸入項目,輸出項目也得要做淨化,才能確保你的程式碼是以安全的方式增進效能,而理解淨化的重要性後,再來確實挑選transient與快取,而針對於大量使用transient,因為是進到資料庫拿資料難免比較慢,而且在同時間他並沒有多執行緒的支援,你會需要非同步的套件來幫助你使用,Async Transients是個還不錯的選擇

reference

WP-object_cache::set
Better caching in Wordpress
wordpress - transients api
The Deal with WordPress Transients
PHP Performance Tuning: 12 Simple Tips
Improving WordPress Transients


上一篇
「Wordpress 外掛開發」外掛的權限偵測與安全性 nonce/Kses/wpdb
下一篇
「Wordpress 外掛開發」Worpdress 的核心鉤子 Hook - action
系列文
Wordpress 外掛開發30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言