ワードプレスに独自テーブルを追加するなどもをかし。

WordPress

wp-db.phpをいじってはいけない!!

やり方を検索してみるとたくさんヒットするやり方が wp-includes/wp-db.php を直接編集するというもの。

wp-includesやwp-admin内のコアファイルを直接編集するということは、絶対にやってはなりません!!!『絶対にダメ』です。

ワードプレスで利用するテーブルのリスト

通常、ワードプレスをインストールする際にはユーザーがデータベースを準備して、その情報を wp-config.php に記述します。でも、テーブルをユーザーが作ることはないですね。ワードプレスのインストール時に必要なテーブルは自動的に生成されます。
この作業は /wp-admin/includes/schema.php に記述されています。

あと、意識することも無いのですが、プラグインを追加した時にプラグイン独自のテーブルが生成されているなんてこともあります。

上で直接編集するな!!と言った wp-includes/wp-db.php では、 wpdb というクラスが定義されています。 $wpdb というオブジェクトをグローバルで利用できるようにするための仕組みで、これによってデータベースとのデータのやり取りはほぼ全てカバーされています。

このファイルの255行目〜466行目あたり(Wordpress 5.7.2の場合)に、データベース内で、ワードプレスがどのテーブルを使うか、というリストがあり、 $tables という配列におさまっています。

/**
     * List of WordPress per-blog tables.
     *
     * @since 2.5.0
     * @see wpdb::tables()
     * @var array
     */
    public $tables = array(
        'posts',
        'comments',
        'links',
        'options',
        'postmeta',
        'terms',
        'term_taxonomy',
        'term_relationships',
        'termmeta',
        'commentmeta',
    );

〜後略〜

これがどういうことかというと、 $tables 配列に記述されていないテーブルは、基本的にはデータベース上に存在していてもワードプレスは読み込んでくれない、つまり、独自にデータベースにテーブルを追加した「だけ」では、ワードプレス上では使えないのです。

なので、この $tables に追加するテーブル名を追記してやる必要があるということで、この wp-db.php に直接記述するということをやる馬鹿が出現するわけです。

wp-db.phpを直接編集せずに実現するには?

とりあえず wp-db.php の冒頭部分(46行目あたり)を読め。

* It is possible to replace this class with your own by setting the $wpdb global variable
* in wp-content/db.php file to your class. The wpdb class will still be included, so you can
* extend it or simply use your own.

ちゃんと教えてくれてる。

wp-content ディレクトリ直下に db.php というファイルを作ったらそれを読み込んであげるよ、と。いわゆる「ドロップイン」というやつです。変更部分だけをextendしたらいいと。ちゃんと教えてくれてるじゃん。

※ ドロップインについてはこちらが分かりやすいです。

ドロップインでWordPress本体をカスタマイズする。機能拡張のためのテンプレート

実践

さて、では例えば、独自テーブルとして「history」といったものを追加したい場合を考えます。

wp-config.php で指定したデータベースのプレフィックスが

/**
 * WordPress Database Table prefix.
 *
 * You can have multiple installations in one database if you give each
 * a unique prefix. Only numbers, letters, and underscores please!
 */
$table_prefix = 'wp_';

ならば、使用中のデータベースに追加すべきテーブル名は

wp_history

となります。

phpMyAdminを使うなり何かのツールを使うなりして、テーブル wp_history を加えましょう。

次に、 wp-content 直下に db.php というファイルを作り、以下のように記述します。

<?php
require_once(ABSPATH.WPINC.'/wp-db.php');

class my_wpdb extends wpdb {
    public $tables = array(
        'posts',
        'comments',
        'links',
        'options',
        'postmeta',
        'terms',
        'term_taxonomy',
        'term_relationships',
        'termmeta',
        'commentmeta',
        'history' // ←加えた!
    );
}

if( !isset($wpdb) ) {
    $wpdb = new my_wpdb( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
}

注意する点は、配列 $tables に加えるテーブル名はプレフィックスを除いたものであること。

とりあえず読み込んでいることを確認

さて、結果をテストしたいんだけれども、今インストールしたてでまだ湯気が出てるぐらいのワードプレスなので、どうしたものか。

とりあえずデフォでテーマはtwentytwentyoneになっているようなので、テーマフォルダの page.php を複製して page-sample.php とでもしておき、冒頭に

<?php
  /*
   * Template Name: テストページのテンプレ
   */
?>

これだけ加え、固定ページ→サンプルページにこのテンプレファイルを適用する。

とりあえずこれで任意のPHPコードを表示する準備はできた、と。


wpdbクラスの使い方については公式のcode referenceを参照(英語)。
Code Reference - wpdb


ちなみに、追加したwp_historyテーブルにはこんなデータを格納しました。

ID year event
1 794 鶯が鳴いたり平安京ができたり。
2 710 平城京はなんとも綺麗。

では、page-sample.phpのループ外

while ( have_posts() ) :  〜  endwhile; // End of the loop. 
// これの外側

のどこでもいいからちょっと落書き。
とりあえずちゃんとテーブルからデータを取ってきてることだけ確認できたらいい。

<?php
    global $wpdb;
    $results = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}history");
    print_r($results);
?>

出力結果(htmlソースの方で見てます)は

Array
(
    [0] => stdClass Object
        (
            [id] => 1
            [year] => 794
            [event] => 鶯が鳴いたり平安京ができたり。
        )

    [1] => stdClass Object
        (
            [id] => 2
            [year] => 710
            [event] => 平城京はなんとも綺麗。
        )

)

ちゃんと取得できてる。

めでたしめでたし。

ちょいと不可解な展開が・・・

変更を巻き戻してみると・・・?

とりあえずちゃんとテーブルを認識してデータ取得ができたところで、上で追加した wp-content/db.php を読み込まなかったら(データベース上のテーブルはそのまま)、テーブルを読んでくれないことを確認してみよう。

あくまでも確認です。

ん?なんじゃ?

読み込めてるwww あれ?読み込めないんじゃなかったんかいな。

最初から$tablesに追加しないテーブルを用意する。

ということでちょっと実験してみましょう。
プレフィックス有り/無しでテーブルを一つずつ追加して、db.phpは用意せず、テーブルを読み込むかどうか実験する。

テーブルは

  • プレフィックスあり wp_geograpy

  • プレフィックスなし geograpy

以下のものを追加する。

テーブル:wp_geograpy

id country
1 japan
2 china

テーブル:geography

id country
1 USA
2 canada

で、出るべき結果は、「これら二つのテーブルはどちらもWPで読み込まれませんでした」というものですが、この流れだと、「プレフィックス有りの方は読み込みましたが、プレフィックス無しの方は読み込みませんでした」という結果ならギリ納得せざるを得ないかも。
そんな感じでいざスタート!


出力テスト

<?php
    global $wpdb;
    // プレフィックス付き
    $result1 = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}geograpy");
    print_r($result1);
    // プレフィックス無し
    $result2 = $wpdb->get_results( "SELECT * FROM geograpy");
    print_r($result2);
?>

出力結果

Array
(
    [0] => stdClass Object
        (
            [id] => 1
            [country] => japan
        )

    [1] => stdClass Object
        (
            [id] => 2
            [country] => china
        )

)
Array
(
    [0] => stdClass Object
        (
            [id] => 1
            [country] => USA
        )

    [1] => stdClass Object
        (
            [id] => 2
            [country] => canada
        )

)

あちゃ〜〜・・・両方出力できてるやん・・・

データ書き込みをテストしてみる

プレフィックスの有無に拘わらず、$tablesへの記述も無しにデータを読み出せてしまいました。
じゃあ書き込みもできるのでしょうか。まあできるんだろうなぁ・・・。
ということでやってみます。


wpdbクラスを利用してテーブルにデータを書き込むメソッドは以下の通り。

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

二つのgeograpyテーブルにデータを書き込んでみます。

公式のサンプルコードを見ると、この$tableにはプレフィックスを含まないように見えるんだけど、どうなんだろう?そうだとすると、プレフィックス無しのテーブルはここで脱落するのではなかろうか?プレフィックス有り/無し両方でやってみます。

<?php
    global $wpdb;
    // プレフィックス有り
    $wpdb->insert( 
        'wp_geograpy', 
        array( 
            'id' => '', 
            'country' => 'korea', 
        ), 
        array( 
            '%d', 
            '%s', 
        ) 
    );
    $result1 = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}geograpy");
    print_r($result1);

    // プレフィックス無し
    $wpdb->insert( 
        'geograpy', 
        array( 
            'id' => '', 
            'country' => 'mexico', 
        ), 
        array( 
            '%d', 
            '%s', 
        ) 
    );
    $result2 = $wpdb->get_results( "SELECT * FROM geograpy");
    print_r($result2);

?>

出力結果

Array
(
    [0] => stdClass Object
        (
            [id] => 1
            [country] => japan
        )

    [1] => stdClass Object
        (
            [id] => 2
            [country] => china
        )

    [2] => stdClass Object
        (
            [id] => 3
            [country] => korea
        )

)
Array
(
    [0] => stdClass Object
        (
            [id] => 1
            [country] => USA
        )

    [1] => stdClass Object
        (
            [id] => 2
            [country] => canada
        )

    [2] => stdClass Object
        (
            [id] => 3
            [country] => mexico
        )

)

よっしゃ完璧!!!

・・・ってなんでやねん!

書き込みも出来てるし。db.phpでwpdbクラスに追記してやらなくても、読み書きともに出来てるし。

上の方で、

$tables 配列に記述されていないテーブルは、使用中のデータベースに存在していてもワードプレスは読み込んでくれない、つまり、独自にデータベースにテーブルを追加した「だけ」では、ワードプレス上では使えないのです。

と書いたところなんですけど、どうしてくれますの??

う〜〜〜ん、これは調べてみないとね。

結論:普通に独自テーブルを追加するだけで使える。

とりあえず、db.phpへの記述は念の為にしておいた方が安心ではあるので、やっておきましょう。

けど、無くてもできるで!!みたいな。

う〜〜ん、分からん。

まあ、とりあえずwpdbクラスの各種メソッドを使いこなせるように勉強しましょう、というぐらいですな。

以上!!

WordPressMySQL,Wordpress

Posted by 大将