2013年5月22日水曜日

29.Google App Engine for PHPでWordPressを動かしてみた




Ryo Yamasaki(@vierjp)です。

前回「28.Google App Engine for PHP (GAE/PHP) を早速試してみた」というエントリーを書きましたが、
公式ドキュメントに「Running WordPress」という項目があったのでこちらも試してみました。

せっかく日本人が試すのだから、ということでWordpressも日本語版にしてみました。

※後述しますがかなり厳しい問題が一点未解決です
 2013/6/14追記 この問題を解決するWordPress用プラグインが公開されました。
Blog @vierjp : 36.Google App Engine for PHP上でWordPressを運用するためのプラグインが登場



◯構築手順


基本的に公式ドキュメントの通りです。

・WordPress 日本語版をダウンロードする

WordPress › 日本語
今回テストに使用したのは3.5.1です。
日本語版は公式(英語版)とは別に提供されています。
これだけ有名なプロダクトなのに、公式で多言語対応していないのがちょっと驚き。

WordPress › 日本語 « WordPress 日本語版について
(オリジナル英語版と日本語版との違い)


CloudSQLの準備

CloudSQLは一番小さい「D0」のインスタンスを現在無料で使う事ができます。

ただし、Billingは有効にしておく必要があります。
6月までは無料」とのことですが、
無料期間が終わると自動的に有料プランに移行して引き落としが始まる、というよくあるパターンなのでしょう。


* 古いUIから作ってしまいました


DBの初期設定


「Import data」から「gs://appengine-php/setup.sql 」をインポートするか、
「SQL Prompt」から以下を1行ずつ実行します。

CREATE DATABASE IF NOT EXISTS wordpress_db;
CREATE USER 'wp_user'@'localhost' IDENTIFIED BY 'wp_password';
GRANT ALL PRIVILEGES ON wordpress_db.* TO 'wp_user'@'localhost';



アプリの作成

・ディレクトリ構成

アプリケーションのディレクトリとして「wordpress-gae」を作成した上で、
以下の構成にしています。

wordpress-gae
├wordpress ←ダウンロードして展開したWordpressのディレクトリを丸ごと配置
|├wp-admin
|├wp-content
|├wp-includes
|├index.php
|├wp-config.php←以下の手順で修正
|└・・・
├app.yaml ←以下の手順で新規作成
├cron.yaml ←以下の手順で新規作成
└php.ini ←以下の手順で新規作成


・app.yaml
application: YOUR_PROJECT_ID
version: wordpress
runtime: php
api_version: 1
threadsafe: true

handlers:
- url: /(.*\.(htm$|html$|css$|js$))
  static_files: wordpress/\1
  upload: wordpress/(.*\.(htm$|html$|css$|js$))
  application_readable: true

- url: /wp-content/(.*\.(ico$|jpg$|png$|gif$))
  static_files: wordpress/wp-content/\1
  upload: wordpress/wp-content/(.*\.(ico$|jpg$|png$|gif$))
  application_readable: true

- url: /(.*\.(ico$|jpg$|png$|gif$))
  static_files: wordpress/\1
  upload: wordpress/(.*\.(ico$|jpg$|png$|gif$))

- url: /wp-admin/(.+)
  script: wordpress/wp-admin/\1
  secure: always

- url: /wp-admin/
  script: wordpress/wp-admin/index.php
  secure: always

- url: /wp-login.php
  script: wordpress/wp-login.php
  secure: always

- url: /wp-cron.php
  script: wordpress/wp-cron.php
  login: admin

- url: /xmlrpc.php
  script: wordpress/xmlrpc.php

- url: /wp-comments-post.php
  script: wordpress/wp-comments-post.php

- url: /(.+)?/?
  script: wordpress/index.php


上記をコピペして「YOUR_PROJECT_ID」を書き換えればOK。
公式ドキュメントの記述に「wp-comments-post.php」を追記しています。(後述)
https://developers.google.com/appengine/articles/wordpress

・php.ini
google_app_engine.enable_functions = "php_sapi_name, gc_enabled"

・cron.yaml
cron:
- description: wordpress cron tasks
  url: /wp-cron.php
  schedule: every 2 hours

・wp-config.phpの修正
/** WordPress のためのデータベース名(書き換える) */
define('DB_NAME', 'wordpress_db');

/** MySQL データベースのユーザー名(書き換える) */
define('DB_USER', 'wp_user');

/** MySQL データベースのパスワード(書き換える) */
define('DB_PASSWORD', '********');

/** MySQL のホスト名(書き換える) */
//define('DB_HOST', 'localhost');

if(isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'],'Google App Engine') !== false) {
  define('DB_HOST', ':/cloudsql/*****:*****');
}else{
  define('DB_HOST', 'localhost');
}

/** AppEngineのドキュメントに従って以下を追加 */

// Cronを無効化(WordPress自身による処理を無効にしてcron.yamlで直接呼び出すような感じ?)
define ('DISABLE_WP_CRON', 'true');

// プラグインやテーマのアップグレードを無効化
define ('DISALLOW_FILE_MODS', 'true');


DB_HOSTは自動的にローカル環境と本番環境で接続先を切り替えるように分岐しています。

・参考:WordPressのwp-config.phpで出来る事いろいろ - かちびと.net


デプロイ


前回同様アプリケーションのディレクトリ(wordpress-gae)で以下を実行します。

/Users/User/appengine_php_1_8_0/appcfg.py update -R --runtime=php .

デプロイ後に初めてアプリにアクセスすると「初期設定のためのウィザード」が表示されます。
特に問題なく設定は完了し、管理画面にログインできます。



◯正常動作を確認できた事

・初期設定ウィザード
・ブログの参照
・コメントの投稿
・記事の投稿・編集
・カテゴリの追加
・固定ページの追加
・テーマの追加
 追加したテーマは「New World
・テーマの「有効化」
・テーマの「カスタマイズ」
・ウィジェットの変更

 *コメントの投稿をするためにドキュメントからコピペしたapp.yamlに以下の記述を追加する必要がありました
- url: /wp-comments-post.php
  script: wordpress/wp-comments-post.php

◯正常動作を確認できなかった事

・テーマの「ライブプレビュー」
・画像のUpload
 これが大きな課題として残りました。
 AppEngineはローカルのファイルシステムにファイルを書き込みできないし、
 Cloud Storageの設定もしていないのだからまぁ当然かと思っていたら、
 少し根が深そうです。

 内部で「$_FILES」という変数を使っていて、
 本来ファイルをUploadした場合自動でファイルが一時ディレクトリに格納され、
 その後move_uploaded_file関数で任意の場所に移動する、という流れらしいですが、
 AppEngineの制限でローカルディレクトリへのファイルの書き込みを許可していないためか
 「$_FILES」の情報が空になってしまっています。

if ( isset( $_FILES["async-upload"] ) ) {
    syslog(LOG_INFO, "_FILES['async-upload'] is set.");
}else{
    syslog(LOG_INFO, "_FILES['async-upload'] is not set."); // ←こちらに分岐する
}

 画面上のエラーメッセージ
ファイルが空のようです。中身のあるファイルをアップロードしてください。このエラーは php.ini ファイルでアップロードができない設定になっているか、post_max_size が upload_max_filesize よりも小さく設定されているために発生している可能性もあります。

 にしたがって、php.iniで
post_max_size=5M
upload_max_filesize=2M

 と指定してみてもダメ。エラーコードも取得できず。
 何か見落としているのでしょうか・・・?(・ัω・ั)

 「PHP アップロード」でググるとどのページも「$_FILES」の説明をしているあたりおそらく定番だと思うので、
 もし現状サポートしていないなら
 内部的にCloud Storageを使うでもいいから「$_FILES」がそのまま動くようにAppEngine自身がサポートしないと
 既存のアプリを載せた際にファイルアップロード機能が動かないケースが多そうな気がします。

 ・参考:$_FILES - 初心者向けPHPナビ

 2013/6/14追記 この問題を解決するWordPress用プラグインが公開されました。
Blog @vierjp : 36.Google App Engine for PHP上でWordPressを運用するためのプラグインが登場



◯まとめ

日本語の投稿も特に問題なくそこそこ動くのですが、
重要な機能としてはファイル(画像)のUploadができませんでした。
この問題さえなければ実用レベルで使えそうな勢いだっただけに残念(´・ω・`)

PHPはまだLimited Previewなので、今後に期待したいと思います。
・・・私がPHPド素人なのが原因の可能性も十分にありますが(´・ω・`;)
PHPに詳しい方、$_FILESが空になる(PHP的な)原因に心当たりがあれば情報くださいませ。m(´・ω・`)m

* 2013/5/22追記 Google+で +Takashi Matsuo さんから教えていただきました。
https://developers.google.com/appengine/docs/php/googlestorage/overview
createUploadUrl  を使うようにしないとだめでしょうね。上記ドキュメントの最後に普通のファイルアップロードは失敗すると書いてあります。

「About Direct File Uploads」のところに
Direct file uploads to your POST handler, without using the App Engine upload agent, are not supported and will fail.
と書いてありました。
結論、AppEngine的な制限についての私の見落としでした。
Google Cloud Storageにアップロードするようにコードの修正が必要になりそうです。

* 2013/5/23追記 はてブで提案をいただいたので試してみました。

php.iniで
upload_tmp_dir=gs://[bucket名]
としてみましたが、残念ながらダメでした。(´・ω・`)
実際にこれができたらシンプルでいいなぁ。

ブログに晒すと情報もらえていいですね。ありがとうございます。(´▽`)


WordPressは以下に配置してあるので、興味があればアクセスしてみてください。
・WordPress on Google App Engine for PHP by vierjp
管理画面に入るにはIDとPassが必要になってしまいますが、記事の参照とコメントの投稿はできます。
* 6月になってCloud SQLが有料になったら止めるかも。
* 2013/11/10 追記 Cloud SQLの課金が地味に痛いので停止しました。

1 件のコメント:

  1. Hi Stuart.
    Thanks for your comment.
    I'm looking forward to your work!

    Thanks,
    Ryo

    返信削除