用ChromePHP 探索 WordPress 佈景主題的運作機制
| 2012/04/11 | 留言
也許你用了一陣子 WordPress,也拿它來開發了許多專案,對於 WordPress 底層的運作有點概念,但一直沒有機會更清楚地理解TMD到底裡頭是發生了啥事,那麼這篇文章也許可為你的探險之路開啟一扇窗。因為專案需求,我用 ChromePHP 寫了一個 wordpress 的小plugin,主要是為了觀察WordPress佈景裡頭的每個頁面,到底暗中執行了哪些SQL,還有WP內建的那一堆常看到的global變數 (像是$wpdb, $post…) 又到底被放進了哪些東西。
ps.如果你只是拿WP來做一些小網站,未來也不太有機會拿 WordPress 做中大型的網站或開MU做深度應用,那就可以先別往下看了,因為內容我想應該不太適合你XD。
安裝後的效果是?
先來個看圖說故事好了,在安裝這個小plugin之前,必須先裝 chromePHP ,注意,這一切都只支援Google Chrome瀏覽器,裝完後你的Chrome右上角就會出現它的小圖示,記得開啟它:
安裝我自己寫的這個小plugin後 (或者把code寫在functions.php當然也行) ,開啟任何一頁 WordPress 網站頁面,打開 Chrome 的開發工具 (網頁上右鍵>檢查元素),點選”Console”頁籤,就可以發現這個頁面的底層做了啥事XD (一個普通的twenty-ten佈景首頁,就執行了38個大大小小的SQL queries,不過我的本機環境有開mu,所以應該會比較多一點):
目前基本的就是查看有多少Loop,執行了多少次SQL,總時間及最耗時的SQL查詢也會列出。展開圖中的「SQL查詢詳情」,就可以看到所有在此頁面執行的SQL的明細:
再下一張是Loop裡的主角-WP_Query物件的內容,因為例子是在首頁,所以可見到 is_home 是 true:
如果你看過twenty-ten佈景的原始碼,對WordPress Loop的運作也有基本的了解,你就會知道為啥這個頁面開出來會有兩個Loop,在此就不贅述。
然後,如果你進入的是單一頁面 (is_singular為true,就是像頁面(page),文章(post)等這種單一頁面),還可查看 $post 裡有啥鬼東西:
Plugin的實作方法
本想直接放下載連結,但目前還不夠滿意,所以先放上可呈現上述效果的code,有興趣的朋友可以慢慢tune成自己要的工具,或等我有空將plugin發佈出來。
首先你的 wp-config.php 需要加上:
[code lang=”php”]
// 讓WP將所有Queries存起來,請注意會影響效能,資料量愈多愈明顯,所以不建議用在正式環境。
define(‘SAVEQUERIES’, true);
[/code]
接著請去剛提到的 http://www.chromephp.com/,下載 ChromePHP.php,放進你目前所使用的佈景目錄裡的 lib目錄。(lib目錄自行建立即可)
再來就是要加入的code,以下預設為你將它加在 functions.php 先試玩:
[code lang=”php”]
// 把 ChromePHP.php 弄進來
add_action(‘init’, ‘__inc_chromephp’);
function __inc_chromephp(){
ob_start();
include ‘lib/ChromePhp.php’; //如果放在其他目錄記得自行修改~
}
// 每個loop開始時就印出log來瞧瞧
add_action(‘loop_start’, ‘__echo_loop_start’);
function __echo_loop_start($post){
ChromePhp::groupCollapsed(‘WP Loop 資訊’);
// 如果$post變數資料多,可能導致RESPONSE HEADER爆掉。
ChromePhp::log($post);
ChromePhp::groupEnd();
}
// 整頁的資料跑得差不多時,就輸出SQL記錄
add_action(‘wp_footer’, ‘__echo_SQL_queries_details’);
function __echo_SQL_queries_details()
{
global $wpdb, $post;
$query_table[] = array("SQL", "Execution Time", "Calling Function");
$expensive_query_time = 0;
$expensive_qnum = 0;
$expensive_query = "";
$total_time = 0;
$num = 1;
if (is_singular())
{
ChromePhp::groupCollapsed(‘$post 變數’);
ChromePhp::log($post);
ChromePhp::groupEnd();
}
ChromePhp::groupCollapsed(‘SQL 查詢詳情’);
foreach($wpdb->queries as $query)
{
$query_table[] = array($query[0], $query[1], $query[2]);
if($query[1] > $expensive_query_time)
{
$expensive_query_time = $query[1];
$expensive_query = $query[0];
$expensive_qnum = $num;
}
$total_time += $query[1];
ChromePhp::group(‘SQL查詢’.$num++);
ChromePhp::log($query[0]);
ChromePhp::log(‘(花費: ‘, round($query[1],5)." 秒)");
ChromePhp::groupEnd();
}
ChromePhp::groupEnd();
//ChromePhp::group($wpdb->queries); // 這個也很容易讓HEADER爆掉!
$total_queries = count($wpdb->queries);
ChromePhp::log(‘總共執行SQL查詢數目: ‘, $total_queries);
ChromePhp::log(‘總執行時間: ‘, round($total_time,5).’ 秒’);
ChromePhp::group(‘最耗時的查詢: (查詢’.$expensive_qnum.’)’);
ChromePhp::log($expensive_query);
ChromePhp::log(‘花費: ‘.round($expensive_query_time,5).’ 秒’);
ChromePhp::groupEnd();
ob_end_flush();
}
[/code]
就這樣,謝謝收看,記得按讚XD。
本文作者是Audi Lu