Skip to content

【第 18 天】WordPress 操作資料庫

Last updated on 2020 年 10 月 30 日

我們寫外掛的時候,會要存資料到資料庫去,一般來說我們就存在 wp_options 表中,可以參考我在第十天分享的內容:如何修改 WordPress 的後台設置選項。或者就是可以存到 postmeta 或 usermeta 表中,可以參考第十一天的文章:如何管理 WordPress metadata

不過還是會有些時候,這些不能滿足我們的需求,那我們就得需要單獨操作資料表了。這篇文章會來講講如何在寫外掛的時候去操作資料表。

創建資料表

一般在寫外掛時,創建資料表有如下三個步驟:

  1. 寫一個 PHP 函式負責建立資料表。
  2. 外掛啟動的時候去呼叫這個函式。

一個 PHP 函式負責建立資料表

我們定義這個函式叫做 eric_crate_table() ,會長成這樣:

function eric_crate_table() {
    global $wpdb;
    $table_name = $wpdb->prefix . "eric";
    if($wpdb->get_var("show tables like '$table_name'") != $weixin_robot_texts_table) {
        $sql = "CREATE TABLE " . $table_name . " (
              `id` bigint(20) NOT NULL AUTO_INCREMENT,
              `title` varchar(255) CHARACTER SET utf8 NOT NULL,
              `description` text CHARACTER SET utf8 NOT NULL,
              PRIMARY KEY (`id`),
              UNIQUE KEY `keyword` (`keyword`)
            ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
        ";
        require_once(ABSPATH . 'wp-admin/includes/upgrade.php');

        dbDelta($sql);
    }
}

接著我們逐一解釋。首先,預設 WordPress 資料表都是以 wp_ 開頭,但也是會有例外,所以我們向 WordPress 資料庫建立表的時候,要先找找到資料庫表開頭。我們可以在變量 $wpdb->prefix 找到,如下:

global $wpdb;
$table_name = $wpdb->prefix . "eric";

接著,我們得去判斷表是否存在,我們可以通過一條 SHOW TABLES SQL 查詢來判斷。

if($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name)

再來就是實際來創建一個資料表了。這裡不用直接的 SQL 查詢來創建,而是使用在 wp-admin/upgrade-functions.php 中的 dbDelta() 來建立,所以我們需要載入這個文件。 dbDelta() 函式很方便,他可以用來協助我們檢查當前的表結構。

$sql = "CREATE TABLE " . $tablename . " (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `title` varchar(255) CHARACTER SET utf8 NOT NULL,
      `description` text CHARACTER SET utf8 NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');

dbDelta($sql);

外掛啟動的時候呼叫創建資料表的函示

我們使用 register_activation_hook() hook 去掛上剛剛我們建立的 eric_crate_table() 函式。關於 register_activation_hook() 這個 hook 的介紹,可以參考我在第六天的介紹:WordPress 啟用、停用、刪除外掛 。

register_activation_hook( __FILE__,'eric_crate_table');

操作資料表

對於 WordPress 核心的文章、頁面、使用者…這類的資料,我們都可以可以通過 WordPress 內建的函式來完成,例如:我們可以透過 query_posts 來查詢文章。

但是,在很多時候,我們可能會定義自己的資料結構,這時,我們就需要了解 WordPress 的 WPDB,並嘗試借助 WPDB 來完成資料的操作。

在使用 WPDB 時,會需要掌握一定的 SQL 基礎,不過 SQL 基礎已經超過這篇文章的範圍了,我就不贅述。如果還不會使用 SQL 對資料庫進行增刪查改,那麼可能要先去學習一下 SQL 的基礎內容,再來繼續看下去。

初識 WPDB

WPDB 讓我們可以輕鬆的實現對 WordPress 資料庫的操作,讓我們可以完成自定義的資料操作需求。在使用 WPDB 時,我們可以直接使用 WordPrss 提供的 $wpdb 全局變數即可。

global $wpdb;

執行查詢

我們也可以使用 WPDB 進行 SQL 語句的查詢。我們會使用 $wpdb 的 query()

global $wpdb;
$wpdb->query('query');

這個方法將會返回所執行的 SQL 語句影響的行數。如果回傳值是 0 或 false ,表示語句有問題。

獲取一行資料

在執行資料庫時,大部分時候需要查詢某筆資料。這個時候,就可以使用 get_row() 來取得。

global $wpdb;
$wpdb->get_row('query', output_type, row_offset);

get_row() 有三個參數:

  1. 需要執行的 SQL 語句。
  2. 輸出結果的類型,我們可以將其設置為 object ,就是輸出一個物件。將其設置為 ARRAY_A,會回傳一個 Key-Value 形式的陣列;設置為 ARRAY_N,回傳一個排序過的陣列。
  3. 設置我們的資料是否要跳過多少行,默認為 0,即取第一個資料。

取得查詢結果

剛剛我們去抓單個資料,但在某些情況下,我們需要取得某一個類型的所有資料。在這個時候,可以使用 get_results()

global $wpdb;
$wpdb->get_results('query', output_type);

插入資料

除了查詢以外,插入新的資料對於我們來說,也是非常重要的。 WordPress 同樣提供了插入的方法 insert()

global $wpdb;
$wpdb->insert( $table, $data, $format );

執行 insert() 時,需要設置表名,並設置要添加的資料(預設需要是一個資料陣列)。 $format 是插入的類型,預設是 array ,不需要做修改。

在執行完成 insert 後,我們可以通過 $wpdb->insert_id 獲得插入後在表內的 id。

更新資料

我們會查詢和新增了,接著我們還會遇到需要更新的時候,此時,我們可以執行 update() 來更新。

global $wpdb;
$wpdb->update( $table, $data, $where, $format = null, $where_format = null );

update() 的參數和前面幾個比,多了很多,但是其實也不難,我們來一一拆解。

在使用 update() 時,需要 $table 設置資料表名。 $data 則需要傳入我們要更改的資料,傳入的值為也是陣列類型。$where 則是傳入我們要抓來更新的條件陣列。$format 則是我們輸入的 data 的類型,預設是 array ,一般來說不需要動到。$where_format 則是是我們查詢的 where 的類型,預設也是 array,一般來說也不太會去修改他。

刪除資料

剩下最後一個操作了,就是刪除。我們可以使用 delete() 來刪除。

global $wpdb;
$wpdb->delete($table, $where, $where_format = null );

在使用 delete() 時,我們一樣需要 $table 設置資料表名。$where 則是傳入我們要抓來刪除的條件陣列。$where_format 則是是我們查詢的 where 的類型,預設 array,一般來說不太會去修改他。

WordPress SQL 查詢語句安全檢查

WordPress 外掛如果想要上架到 WordPress.org 的話,會需要通過官方的安全檢查。

WordPress 的外掛審核團隊在審核外掛的時候,最主要的就是審查安全問題(通常也不會太在意你的外掛具體功能是什麼)。因此,在開發時,我們需要檢查我們的 SQL 語句安全,不會出現安全問題。

我們最怕的就是使用者在我們前台表單輸入資料的時候,做一些壞壞的事情,可能是 SQL injection 之類的(關於 SQL injection 可以上網 Google ,這也超出本篇範圍了,所以也不贅述。)。

因此, WordPress 官方提供了 prepare() 函式來協助我們預防使用者做壞事。該函式可以將使用者的輸入進行安全的轉換,從而確保進入資料庫的語句都是安全的。

$sql = $wpdb->prepare( 'query' [, value_parameter, value_parameter ... ] );

在使用時,我們需要使用 %s ,這樣的方式來替換 SQL 語句中的值,然後在第二個參數中的數組中傳入對應的值,進而進行 SQL 的處理,確保 SQL 語句的安全,就像這樣:

$wpdb->prepare( "
    INSERT INTO $wpdb->postmeta( post_id, meta_key, meta_value ) VALUES ( %d, %s, %s )", 
        10, $metakey, $metavalue )

對於 WordPress 的資料庫操作介紹差不多就到這邊,wpdb class 底下還有很多好用的方法,可以直接去官方文件參考:wpdb

Published in2020鐵人賽WordPress

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *