wpdbを使ってDBアクセスしてみた

PHP
この記事は約9分で読めます。

WordPressプラグインをつくって遊んでます。

リンク先をブログカード風に表示

リンク先を「はてなブログカード」で表示させる「popo-HatenaBlogCard」というのを公開しています。

「iframe(インラインフレーム)」という仕組みを使って「はてなブログカード」をそのまま表示させています。

見栄えも良いし、表示速度にも問題は無いし、良い事づくしな感じです。

はてなブログカードを表示させるサーバーの能力を間借りして表示させている状態なので、「サービス的に問題無いのかな?」とも思ったのですが、こちらのmbdb(モビデビ)さんの記事を見てみると、はてなさん的にはWordPressとかで使っても問題なさそうな感じです。

そんなわけで「popo-HatenaBlogCard」は名前のとおり「外部リンクは『はてなブログカード』を表示させて、ついでに内部リンクは似てるけどオリジナル形式で表示させる」プラグインという感じで落ち着こうと思います。

 

とはいえ、やっぱり自前でやってみたくなるものです…Σ(゚ロ゚)o゙

つくりなおし&プラグイン名をつけなおし

「はてなブログカード」は、リンク先を「新しいウィンドウで表示」するようになっていたため、内部リンクの場合でも新しいウィンドウ(タブ)で表示されてしまいました。

このため、内部リンクはオリジナル形式で表示させる機能をつくっていました。

外部リンクもオリジナル形式で表示させるようにするわけですが、毎回リンク先からタイトルとか本文を取得していると時間がかかってしまいます。

取得した内容を用意したDB(データベース)のテーブルに保管しておいて、次回以降はそこから読み込んで表示するような「キャッシュ」の仕組みを作ります。

 

プラグイン名は「Pz-LinkCard」にする予定です。

プレフィックス(接頭辞)としては「popo-」を使っていましたが、「Pz-」に。

「Pz」は、「ぽぽづれ」的な?発音は「ぴーずぃー」でも「ぴーぜっと」でも「ぽぽづれ」でも。

名称は「ブログカード」でも良かったのですが、ブログ以外もリンクをするのでリンク先をカード形式で表示する「リンクカード」と呼ぼうと思います。(popo-HatenaBlogCardのときも、内部的にはLinkCardと呼んでいたのです。)

DBのテーブルを用意してみる

毎回リンク先から取得すると、サーバー負担をかけてしまうので、「リンク先URLからタイトルや本文などを取得→DBに保存→次回はDBから取得する」という動きにします。

 

プラグインのアクティベーション時にDBのテーブルを作成して、非アクティベーション時に削除をします。

 register_activation_hook (__FILE__, array($this, 'Pz_LinkCard_activation')); // DB作成、パラメータ初期化
register_deactivation_hook (__FILE__, array($this, 'Pz_LinkCard_deactivation')); // DB削除
public function Pz_LinkCard_activation() {
global $wpdb;
$sql = "CREATE TABLE pz_linkcard (
id int NOT NULL AUTO_INCREMENT,
url_key varchar(1024) NOT NULL DEFAULT '',
url varchar(1024) NOT NULL DEFAULT '',
site_name varchar(256) ,
domain varchar(256) ,
linktype int ,
title varchar(256) ,
excerpt varchar(256) ,
thumbnail varchar(1024) ,
favicon varchar(1024) ,
get_date bigint NOT NULL,
PRIMARY KEY ( id ),
UNIQUE KEY ( id ),
INDEX ( url_key )
) ".$wpdb->get_charset_collate()." ;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}

WordPressに用意されている、データベース操作用の wpdb というクラス関数が用意されています。

DBへのアクセスは、$wpdb におまかせします。

global $wpdb;

$wpdb をグローバル宣言しておかないと使えないので、使う前に書いておきます。

 

DBテーブル作成はSQLコマンドを記述する必要があるようなので、「CREATE TABLE テーブル名 (定義)…」という感じで書いて、dbDelta() を実行します。

MySQL なりのDBMSに直接発行するのでは無く、dbDelta() が解釈するようなので、SQLのコマンドなどは大文字で書く、フィールド名は小文字で書く、とか気をつけるところはあるようです。

 

「id」は更新時のキーにします。「url」はURLを生のまま格納、「url_key」は esc_http() してから格納して検索キーとして使い易くしようと思います。ハッシュ値を使うのも楽しいかもしれません。

「get_time」は更新日時。一定期間を過ぎたら再取得するのに使おうと思います。

 

「charset(文字エンコーディング)」は「CHARSET = utf8」でいいと思ったのですが、「$wpdb->get_charset_collate()」でデフォルトの文字セットが取れるようなので、一応これにしておきました。

 

あとで項目を追加しても、dbDeltaで「CREATE TABLE」を発行すると、今あるテーブルはそのままで、追加したフィールドを最後に追加してくれるような動きをしてくれました。

構文にクセがあるけどDBマイグレーションとか考えなくていいから手軽、という感じでしょうか。

 

非アクティベーション時にテーブルを削除(DROP)します。

public function Pz_LinkCard_deactivation() {
global $wpdb;
$sql = "DROP TABLE ".$this->db;
$wpdb->query($sql);
}

アンインストール時に削除でも良いのですが、お手軽にキャッシュクリアできるようにしておきます。

設定画面からキャッシュしている内容を一覧表示して、選んで更新とか削除ができると良いのだと思いますが、そこまでは知識が追いつきません(^-^;

「カスタム投稿タイプ」を作って、そこにキャッシュしちゃう方法も考えたのですが、どうなんでしょう。

カードの内容をキャッシュ(DB)から取得する

外部リンクの場合は、DB に保存された内容が無いか、「$wpdb->get_row()」を使って検索します。

 $data = $wpdb->get_row($wpdb->prepare("SELECT * FROM $this->db WHERE url=%s", $url));
if (!is_null($data->id) and (time() - $data->get_date < 604800 )) {
$title = $data->title;
$excerpt = $data->excerpt;

URLとかは投稿者が記述するはず、とはいえSQLインジェクションは怖いです。

「$wpdb->prepare()」でプレースホルダー経由でパラメータを渡せるようです。

 

esc_http()でエスケープした文字をキーにしようと思ったのですが、そのままで検索できているので、当面このままで。

 

idがnullじゃなかったら取得できていると見なします。

また、現在日時から604,800秒(60秒×60分×24時間×7日)経過していたら、キャッシュの期限切れとして取得する動きにします。

 

リンク先の情報を取得したら、DBに記録します。

idがnullだったら挿入($wpdb->insert)、nullじゃなかったら更新($wpdb->update)します。

更新のときは、第三パラメータが「where」の指定になるので、キーになる id を指定しています。

id は AUTO_INCREMENT が指定されているので、insert のときに内容をセットしなければ、DBにある一番大きい数値+1で格納してくれます。

if (!is_null($data->id)) {
$wpdb->update(
$this->db,
array(
'url' => $url,
'site_name' => $site_name,
'domain' => $domain,
'linktype' => $link_type,
'title' => $title,
'excerpt' => $excerpt,
'thumbnail' => $thumbnail_url,
'get_date' => time()
),
array(
'id' => $data->id
));
} else {
$wpdb->insert(
$this->db,
array(
'url' => $url,
'site_name' => $site_name,
'domain' => $domain,
'linktype' => $link_type,
'title' => $title,
'excerpt' => $excerpt,
'thumbnail' => $thumbnail_url,
'get_date' => time()
));
}

リンク先の取得とキャッシュからの取得

リンク先から情報を取得すると、ひとつのリンクカードを作成するのに1.4秒~2秒かかります。

キャッシュ(DB)から取得すると0.0008秒。

内部リンクの処理が0.002秒~0.007秒ほどなので、内部リンクより速いようです。

 

内部リンクがちょっと遅いのはフィルターフックとかで整形しているからだと思うのですが、キャッシュしてしまうと、修正しても反映されなかったりするので、あまり大きなメリットは無さそうに感じます。

 

さて、テキストはキャッシュできましたが、サムネイルとファビコンはDBへ保存するのはちょっと面倒そうです。

やはり外部のWeb APIを使用するのが良さそうです。

 

次の記事では、cURLを使ってOGP情報とかを取得したところを書こうと思います。

コメント

タイトルとURLをコピーしました