到目前為止,我們尚未寫過任何一行的 SQL 語法來取得資料,主要原因是 WordPress 的內建函式已把資料庫操作的部分都包裝起來,只需要傳參數到函式裡,就可以取得資料。
假如,想要更複雜一點的資料搜尋條件,使用在上一篇文章中所介紹的 WP_Query 類別,也可以解決大部分的情境,很少需要我們自行編寫 SQL 的部分。
內建的函式例如 wp_options
資料表中取得資料的 get_option
,包含其它大部分的函式,會使用 wpdb 類別,處理包裝好的邏輯,轉換成查詢的 SQL 語法,呼叫 $wpdb
實例來執行。
到自定內容查詢用的 WP_Query 類別,底層的依賴的也是 wpdb 類別,來幫它執行資料庫操作。
資料傳遞過程的依賴關係可簡化為下圖。
圖:SQL 查詢的依賴關係
上圖挑選幾個常見的函式和類別舉例它們和 wpdb 類別的依賴關係。
例如:
get_post
函式依賴 WP_Post
類別,但在該類別之中,最後還是使用 wpdb
類別來存取資料表。get_posts
函式依賴 WP_Query
類別,但在該類別之中,最後同樣使用 wpdb
類別來讀取資料表。而這些包裝進 wpdb
中的 SQL 語句,交給最底層的 PHP 擴展的套件處理。因為 mysql 擴展在 PHP 5.5 版本以後已停用,以當今的 PHP 演進情況來看,基本上都是交由 mysqli 來執行 SQL 語句。
註:之所以使用 $wpdb 來包裝,這是一種「依賴反轉」的設計模式,並不是多此一舉的行為。因此最底層的 mysqli 也可以被替換掉。在第 4 天的文章提到的 Drop-in,自行設計 db.php 進行接掌底層的實作即可。
雖然絕大部分的場景,WordPress 都有現成的函式、類別幫我們包裝好了,可以直接使用,但還是會有機會需要自行編寫 SQL 語法,這時候就需要使用到 wpdb 類別。
在 WordPress 核心程式中,load.php
的 require_wp_db
函式負責了 wpdb 類別的實例化工作,如下:
圖:實例化 wpdb 類別
這個函式將 wpdb 類別實例化之後,存到全域變數中。由於此函式在整個 WordPress 核心載入的一開始就會呼叫了,因次不管在佈景主題中,還是我們自行編寫的外掛中,只要使用全域變數 $wpdb
就可以開始進行資料庫的操作。
例如:
圖: 使用全域變數 $wpdb
function prepare( $query, ...$args ) {}
此方法返回格式化後的 SQL 查詢,其中佔位符已被給定的值替換。所有在 SQL 查詢中的資料都必須在執行 SQL 查詢之前使用此方法進行 SQL 轉義,以避免 SQL 注入攻擊。它的語法和 PHP 的 sprintf
相同。
參數說明:
%s
(對於字串)和 %d
(對於整數)。範例:
圖: 使用 prepare 方法進行 SQL 轉義
查詢參數接受和 PHP 函式 sprintf
的佔位符:
%s
:字串%d
:整數)%f
:(浮點數function get_var( $query = null, $x = 0, $y = 0 ) {}
從資料庫中檢索單一變數值。使用的情境為,只需要從查詢中獲得單一值時。
參數說明:
如果查詢返回多行和多列,可以使用 $x
和 $y
參數來指定想要的值的確切位置。
範例:
圖: 使用 get_var 方法取得單一值
查詢 WordPress 資料庫中的 wp_options
資料表,並取得 siteurl
選項的值。以上範例將輸出 WordPress網站的 URL。
function get_row( $query = null, $output = OBJECT, $y = 0 ) {}
用於從資料庫中檢索單行。
參數說明:
此方法根據 $output
參數的值以不同的格式返回特定行的資料。
範例:
圖: 使用 get_row方法取得單行資料
查詢 WordPress 資料庫中的 wp_posts
資料表,並獲取 ID 為 5 的文章的所有資料,以上範例將輸出文章的標題。
function get_col( $query = null, $x = 0 ) {}
從資料表中檢索某一欄 (column) 的所有值。
參數說明:
0
將會是查詢結果中的第一欄位,1
將會是第二欄位,依此類推。預設值為 0
。此方法返回一個陣列,其中包含查詢結果中指定列的所有值。
範例:
圖:使用 get_col 方法取得單欄資料
以上範例從 WordPress 資料庫的 wp_posts
表中獲取所有文章的標題。如果要取得日期,則只要在第二參數傳入索引 1
,欄位加上 post_date,即可取得。
function get_results( $query = null, $output = OBJECT ) {}
從資料表中檢索查詢的多行結果。
參數說明:
此方法根據 $output
參數的值以不同的格式返回多行的資料。
範例:
圖:使用 get_results 方法取得多行資料
查詢 WordPress 資料庫中的 wp_posts
表,並獲取所有文章的標題和日期。
在上面的範例中,$posts_data
是一個陣列,每一行為物件,每個物件都有 post_title
和 post_date
屬性,代表查詢結果中的每一行。
function insert( $table, $data, $format = null ) {}
用於將新資料插入到指定的資料庫表中。
參數說明:
data
格式。可以是一個單一的格式字串(例如,%d
、%s
等),或者是一個格式的陣列。如果未指定,會自動判斷格式。成功時返回 true
,失敗時返回 false
。
範例:
圖:使用 insert 方法新增資料
在 WordPress 資料庫的 wp_options
表中插入一個新的選項。在上述範例中,我們定義了一個 $data
陣列,其中包含要插入的資料使用 insert
方法,將資料插入到 wp_options
資料表中。
function update( $table, $data, $where, $format = null, $where_format = null ) {}
修改、更新資料表中的資料。
參數說明:
data
格式。可以是一個單一的格式字串(例如,%d
、%s
等),或者是一個格式的陣列。如果未指定,會自動判斷格式。where
格式。成功時返回受影響的行數,如果沒有任何行被更新,則返回 0
。失敗時返回 false
。
範例:
圖:使用 update 更新資料
更新 WordPress 資料庫的 wp_options
表中名為 Tiananmen
的選項的值。在上述範例中,$data
陣列定義了要更新的值,而 $where
陣列則定義了哪些行應該被更新。
function delete( $table, $where, $where_format = null ) {}
從資料庫中移除資料。
參數說明:
where
格式。成功時返回被刪除的行數。失敗時返回 false
。
範例:
圖:使用 delete 刪除資料
從 WordPress 資料庫的 wp_options
資料表中刪除名為 Tiananmen
的選項。在上述範例中,$where
陣列定義了哪些行應該被刪除。
function query( $query ) {}
用於執行任何 SQL 查詢,不論是選擇欄位、插入、更新還是刪除資料的操作。
參數說明:
此方法的返回值取決於查詢的類型:
SELECT
、SHOW
、DESCRIBE
或 EXPLAIN
查詢,它將返回結果行的數量。INSERT
、UPDATE
、DELETE
等),它將返回受影響的行的數量。false
。範例:
圖:使用 query 刪除資料
假設你想從 WordPress 資料庫的 wp_options
表中刪除名為 Tiananmen
的選項。
如果是接收來自外部來源的資料時。在這種情況下,必須使用 prepare
進行查詢的安全格式化,以避免被執行 SQL 注入攻擊。
名稱 | 說明 |
---|---|
base_prefix | 定義於 wp-config.php 中的原始前綴。對於多站點:如果您想獲得沒有附加部落格編號的前綴,請使用此選項。 |
$col_info | 最近查詢結果的欄位資訊。 |
$insert_id | 最近的 INSERT 查詢為 AUTO_INCREMENT 生成的 ID。 |
$last_error | MySQL 生成的最近的錯誤訊息。 |
$last_query | 最近已執行的查詢 SQL 語句。 |
$last_result | 最近的查詢結果。 |
$num_queries | 已執行的查詢數。 |
$num_rows | 上一次查詢返回的行數。 |
$prefix | 網站的設定 WordPress 資料表的前綴。 |
$queries | 通過將 SAVEQUERIES 常數設置為 TRUE ,您可以保存在資料庫上運行的所有查詢及其停止時間,並將作為陣列存儲在此變數中。 |
$show_errors | 是否開啟顯示錯誤訊息。預設值為 TRUE 。 |
這些屬性都是公開屬性,可直接使用,但切勿修改它,以免不預期的錯誤發生。例如修改了 base_prefix
,會造成找不到資料表的錯誤。
echo $wpdb->last_query;
以上範例將印出最近一次的 SQL 查詢語句到畫面上。
雖然 WordPress 本身已經提供了大量的內建函式供開發者進行直接操作和資料表關對應的新增、修改、刪除等動作,以及使用高階的 WP_Query 類別來包裝 wpdb 的各種複雜的查詢情境,但仍有不足的時候。
這時候 wpdb 可以讓我們直接與資料庫溝通,無論是最佳化查詢語句,或者用來操作我們設計外掛時自行產生的資料表。因此好好理解及學習 wpdb 的用法是十分有幫助的哦!
參考官方文件:
課後思考:
為什麼在下 SQL 查詢語句之前都要先使用 prepare 方法,如果不使用的話可能會發生什麼事?
前篇解答參考:
WP_Query 雖然在選項參數中提供了許多查詢的條件可以使用,通常查詢有索引的欄位,例如
post_type
、post_name
,不過當使用到沒有索引的欄位作為查詢條件的話,會影響效能。盡量避免這類的操作。