為什麼 WordPress 不建議使用 PHP 中的 extract 函式

如果你找到網路上關於短代碼 shortcodes 的 WordPress 教學,有時會發現以下的範例:

add_shortcode( 'my_loop', 'hyc_shortcode' );
function hyc_shortcode( $atts ) {
  extract( shortcode_atts( array (
    'post_type'      => 'post',
    'posts_per_page' => 10,
  ), $atts ) );
}

$args = array(
  'post_type'      => $post_type,
  'posts_per_page' => $posts_per_page,
);

但根據 WordPress 的 PHP 程式碼撰寫標準,這其實是不建議的作法

extract() 在做什麼

根據 PHP 的說明文件,extract() 會將陣列中的索引鍵與索引鍵值取出,以索引鍵為名稱去定義變數。譬如說:

$arr = array(
  'user_id'    => 0,
  'user_name'  => 'Eric',
);

extract( $arr );

echo $user_id; // 回傳 0
echo $user_name; // 回傳 Eric

然而,你並不知道這些變數是否已經在全域變數中定義過,也不知道是否會觸發到未預期的結果,因此在 PHP 的說明文件中,也特別警告:

如有尚未信任的資料來源,例如 $_GET、$_FILE 或其他使用者輸入值。不要使用 extract()。如果你使用 extract(),必須搭配對應標誌 (flag)。

也因為有許多未預期的結果,會造成偵錯流程困難,以及程式可讀性減低,因此在「編碼標準」中,便明確禁止這個做法。但其實可以看到,許多外掛開發者都還是使用這種作法。

正確的作法

為了提高程式碼的可讀性,因此正確的作法,是將短代碼的參數另外儲存至一個陣列中。我們將上述的代碼改寫:

add_shortcode( 'my_loop', 'hyc_shortcode' );
function hyc_shortcode( $atts ) {
  $a = shortcode_atts( array (
    'post_type'      => 'post',
    'posts_per_page' => 10,
  ), $atts );
}

$args = array(
  'post_type'      => $a['post_type'],
  'posts_per_page' => $a['posts_per_page'],
);

結語

今天這篇文章,主要是說明為什麼不該使用 extract() 這個方法。關於更多 shortcode 的實際作法,可以參考我在鐵人賽的文章,裡面提到如何透過短代碼的機制,來擴展既有短代碼的功能。

參考資料

預設圖片
Eric Chuang
正職是廣告行銷人員,因為 Google Tag Manager 的關係開始踏入網站製作的領域,進一步把 WordPress 當成 PHP + HTML + CSS + JavaScript 的學習教材。此外,因為工作的關係,曾經用 Automattic 的 Underscores (_s) 替客戶與公司官網進行全客製化佈景主題開發。

1 則留言

  1. 感謝 Eric 的解說,之前在寫的時候看到 PHP Sniffer 噴出這個提醒,當下在趕工就直接把它 ignore 掉了 😓,後來重構時為了解決這問題就爬到你的文章,你的部落格很有料啊,已加入 feedly 追蹤,期待你分享更多好文!👍

發佈留言

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料

Physical Address

304 North Cardinal St.
Dorchester Center, MA 02124