32
40

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

WordPressを高機能エディタとして利用し、Firebaseと連携させる

Last updated at Posted at 2018-10-18

WordPressはそのお手軽さと拡張性の高さで、BlogやCMSとして重宝されていますが、単純に入力フォームとして見た場合も有用だったりします。WordPressを入力フォームとしてのみ利用し、FirebaseへPOST/連携させるという、少々ニッチな仕組みを作ったので、そのノウハウと手順を紹介します。

入力画面にWordPressを使う理由

WordPressの選定ポイント

長期的に運用していくサービスへの導入を検討していく上で、他のCMSと比較して、以下のポイントが決め手となりました。

  • 汎用性:LAMP環境下ならほとんどのサーバで動作する汎用性の高さ
  • 信頼性:運用実績が多数あり、信頼性が高い
  • 拡張性:拡張性が高く、カスタマイズが容易、膨大なプラグイン資産が使える
  • 情報量:コミュニティが活発で情報量が多く、エラーが発生した際や開発時に解決できる可能性が高い

Advanced Custom Field Pro(ACF Pro)

WordPressの入力画面としての優秀さを際立たせるのがカスタムフィールドを拡張するAdvanced Custom Field Proです。有料ですがDeveloperライセンスを買えば制限なく他の案件に使えます。
とくに優秀な機能として、Repeater Field(繰り返し入力フィールド)、Flexible Content(柔軟コンテンツ)は、他の入力システムと一線を画す優秀な機能です。このプラグインがあるからWordPressを使っているんだ!といっても過言ではありません。

ACF Pro

セキュリティリスクについて

WordPressのウィークポイントとして、オープンソースで普及率が高いため、利用にはある程度のセキュリティリスクが伴います。しかし、あくまで入力フォームとして使う構成とし、WordPressをインストールしているサーバとフロントエンドを表示するサーバとを分ければ問題ないと判断しました。ベーシック認証で担当者以外のアクセスを弾く、WAFを導入するなどの対策をした上で運用することを推奨します。

構成

firebase-database-wordpress.png

構成は図にするとこんな感じです。WordPressで作成したデータ(商品データや記事データなどの不変データ)を一方通行でFirebaseに受け渡すフローとなります。ユーザデータやフロントエンドで生成されたデータはFireabaseと双方向で連携させています。

役割 ソフトウェア・サービス
記事入力画面 WordPress / LAMP環境サーバ
画像格納             Firebase Storage
データベース        Firebase Realtime Database
フロントエンド Firebase Hosting(htmlが表示できるサーバならなんでも)

WordPress->Firebaseのためのコード作成

1.データ作成処理(WordPress)

WordPressのお作法に習い、themeフォルダー内またはwp-loadを使って記事のデータ生成を行います。今回はデータベースへの登録と同時に、記事内で登録された画像もStorageに登録させる必要があったので、Storageも対応しているkreait/firebase-phpライブラリの利用を前提とした実装になります。Composer経由でダウンロードするか、gitから直接ダウンロードして読み込ませます。

セットアップ

firebaseSync.php
equire '/xxx/autoload.php';
require_once '/xxx/wp-load.php';

// firebase-phpのnamespace設定
use Kreait\Firebase;
use Kreait\Firebase\Factory;
use Kreait\Firebase\ServiceAccount;

/* 
* Firebase Admin SDKのサービスアカウントを登録
* https://firebase.google.com/docs/admin/setup?hl=ja
*/
$serviceAccount = ServiceAccount::fromJsonFile(__DIR__.'/fireabase-admin-json/xxxxxxx-adminsdk-xxxxxxxxx.json');

ループ処理によるデータ生成

Databaseへ登録するデータの生成と同時にStorageアップロード用の画像を格納した配列を作成します。どちらの配列も連想配列にしているのは、重複データを弾くためです。

firebaseSync.php
$partsQueryKey = array(
  'post_status'    => 'publish',
  'order'          => 'DESC',
  'post_type'      => 'xxxx',
  'posts_per_page' => 999
);

$query = new WP_Query($partsQueryKey);
$databaseArray = []; // Firebase Databaseへ登録する連想配列
$storageArray = []; // Firebase Storageへ登録する画像データ用連想配列
$num = 0;

/* 
* WordPressのループ処理でデータ作成
*/
while($query->have_posts()){
  $query->the_post();
  $id = get_the_ID();

  // Database登録用データ
  $databaseArray[$id]['id'] = $id;
  $databaseArray[$id]['name'] = get_the_title();
  $databaseArray[$id]['mainImage'] = get_field('mainImage')['filename'];

  // Storage登録用データ
  $storageArray[$brandsData[$id]['mainImage']] = array(
    'modified' => get_field('mainImage')['modified'], // 画像更新日付を取得
    'src' => get_field('mainImage')['url'] // 画像URLを取得
  );

  $num++;
}

2. データ加工・アップロード(Firebase)

データ生成が終わったら、データの加工処理(必要であれば)とfirebase-phpを使ったデータアップロード処理を行います。
DatabaseへはgetReferenceを使うことで簡単にPOSTできますが、StorageはFlysystemというComposerライブラリで定義されている、Filesystem APIに則り操作する必要があります。ここではputlistContentsのみしか使っていませんので、より詳しく知りたい場合は以下のリンクから確認してください。

Filesystem API | Flysystem

なにも工夫しないで実装した場合、投稿や同期時に、すべての画像がアップロードされてしまいますが、今回のコードではアップロードさせたい画像の連想配列にmodified(画像の更新日時)を含めて、すでにFirebase StorageへPOSTしている画像のmodifiedと比較して、差分配列を作成し、必要のない画像を投稿しないようにしています。
※このサンプルでは、Databaseはitem配下に、Storageはimg配下にPOSTされるように設定しています。

firebaseSync.php

$firebase = (new Factory)
  ->withServiceAccount($serviceAccount)
  ->create(); // firebaseインスタンス作成

$database = $firebase->getDatabase();
$storage = $firebase->getStorage();
$filesystem = $storage->getFilesystem();
$firebaseImageList = $filesystem->listContents('img/'); //アップロードしたいfirebase storageのディレクトリ内画像一覧を取得

// アップロードする画像のみを抽出
foreach ($storageArray as $key => $value) {
  $fimename = $key;
  $timestamp = strtotime($value['modified']);

  foreach ($firebaseImageList as $value) {
    if($fimename == $value['basename'] && $timestamp <= $value['timestamp']) { // 差分抽出
      unset($storageArray[$fimename]);
    }
  }
}

// Storageへの画像アップロード処理(差分処理)
foreach ($storageArray as $key => $value) {
  if($key != null && $key != '') {
    $filename = $key;
    $src = file_get_contents($value['src'], false, stream_context_create($options));
    $filesystem->put('img/' . $filename, $src); 
  }
}

// Databaseへのアップロード処理
$database->getReference('items')->set($itemsData);

最終コードはgistにアップしています。
https://gist.github.com/kgsi/e86123a9e5c6d841ad7c0e153d6358de

所感 

あまり参考記事もなく、一風変わった構成となった気がしますが、WordPressを使い慣れている自分にとって、知識のない他のCMSを使うよりも実装がしやすく、お手軽感がありました。投稿毎にFirebaseへPOSTするのかどうか、全体の書き換えを行わないよう工夫をする必要があったりと、少々手間がかかる部分もありますが、WordPressのカスタム仕様を理解していれば実装は容易かと思います。

自分の場合は、投稿の度にイベントフックして投稿させるよりも、一括してデータを同期させる方法を選びました。以下のようなWidgetを登録し、簡単に同期できるようにしています。

wordpress-sync-widget.png

32
40
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
40

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?