WordPressの機能を拡張して何かを実装してみたい。
BitfilerのAPIを叩いてビットコインの値段を表示する機能を1から作ってみる。
「外観>テーマの編集」からfunctions.phpを編集します
最後の方に以下を追記。
1 2 3 4 5 6 7 8 |
function myfnc_getbtc_yen(){ $api_url = 'https://api.bitflyer.jp/v1/board'; $response = file_get_contents( $api_url ); $result = json_decode( $response ); return "<span style='font-weight:bold'>".$result->mid_price."</span>"; } add_shortcode("btcyen",myfnc_getbtc_yen); |
記事作成の所で [btcyen] と入力すると、ページ画面で値段が表示されます。
これ見てやっと気づいたんですがプラグインの shortcodes ultimate はこうやって作ってるんですね。ソースは以下で見えます。
とりあえず目的は果たせましたが問題は残っています。
PHPはページ読み込み時に実行されます。
なのでwhile-sleepを使って定期更新なんかはできません。
これをするにはフロント側で色々しないといけないと思います。
もう一つ大きな問題として大量アクセスに対応できないと思います。
使用するAPIの制限アクセス数を超えないようにしないといけません。
対策として思いついたのは、
- 更新したい値を含んだファイルを吐き出すプログラムを常駐させる
- 更新したい値を含んだファイルを吐き出すプログラムをcron設定する
- ワードプレスの定期実行(wp_schedule_event)を使う
自由度が高い順に書いてみましたが、Wordpressの管理画面だけで済ませたいので最後の方法でWP-Cronに登録してみます。
(Cronとはありますが設定時間ごとに実行されるわけではなく、実際には一定時間内にアクセスがあっても起動しない関数です。)
1時間ごとにキャッシュファイルにビットコインの値段を保存します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$mycachefile = "/tmp/crypto.cache"; function myfnc_getbtc_yen_event(){ global $mycachefile; $api_url = 'https://api.bitflyer.jp/v1/board'; $response = file_get_contents( $api_url ); $result = json_decode( $response ); $fp = fopen($mycachefile, 'w'); fwrite($fp, $result->mid_price); fclose($fp); } add_action("my_crypto_event", "myfnc_getbtc_yen_event"); if ( !wp_next_scheduled( 'my_crypto_event' ) ) { wp_schedule_event(time(), 'hourly', 'my_crypto_event'); } |
合わせてショートコードの方も修正。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
function myfnc_getbtc_yen(){ global $mycachefile; $g_btcyen = "not found"; if (file_exists($mycachefile)) { $g_btcyen = "can not open"; $fp = fopen($mycachefile, 'r'); if($fp){ $g_btcyen = fread($fp, filesize($mycachefile)); } fclose($fp); } return $g_btcyen; } |
これで一定時間ごとにローカルファイルをアップデートして、それを表示することが可能になりました。
wp_schedule_event
は1時間ごと、12時間ごと、1日ごとしか設定できません。
ちょっと間隔が長すぎるので拡張します。
1 2 3 4 5 6 7 8 9 10 11 12 |
function cron_add_ex( $schedules ) { $schedules['5min'] = array( 'interval' => 300, 'display' => __( 'Every 5 minutes' ) ); $schedules['10min'] = array( 'interval' => 600, 'display' => __( 'Every 10 minutes' ) ); return $schedules; } add_filter( 'cron_schedules', 'cron_add_ex' ); |
これで5分毎、10分毎の設定も可能になります。
スケジュールはWP Crontrolというプラグインを入れることで確認可能です。
「ツール→Cronイベント」が追加され、そこで一覧を確認・操作できます。
所感
大きな勘違い※もあって苦戦しました。
※グローバル変数に入れて定期イベントで代入、ショートコードで参照すれば可能かと思ってました。実際には読み込み時にfunctions.phpが実行される関係でグローバル変数も初期化されてしまい、読み込めませんでした。
今回はfunctions.phpをいじりましたが、ちゃんとプラグインとして作成するほうがよいみたいです。
あとエラーハンドルや拡張性も考えて色々と修正が必要そう。
javascriptに慣れていたとはいえ、1日でWordpressをいじれるくらいに使えたのでPHPは使いやすい言語ですね。