テスト環境にあるWordPressにはテキストウィジェットが2つ設定してあります。そのWordPressを下記の手順で本番環境に移行。
- phpMyAdminでテスト環境のWordPressのデータベースをエクスポート
- エクスポートしたSQLデータをテキストエディタで開き、テキスト環境URLを本番環境URLに置換
- 本番環境のphpMyAdminから、SQLデータをインポート
この段階でデータベースの中身は全く同一。ファイルも全て移行し、本番のWordPressを開くと、なぜかウィジェットが表示されておらず、管理画面をウィジェットの設定画面を開くと、ウィジェットが何も設定されていない状態に。
ウィジェット周りの関数を調べてみる
ちなみにテキストウィジェットのデータは、wp_optionsテーブルのwidget_textにserializeされて格納されています。また、ウィジェットの配置情報はwp_optionsテーブルのsidebars_widgetsにserializeされて格納されています。もちろん、どのデータもきちんと移行できている状況。原因がわからなかったので、ウィジェット関連のスクリプトがまとめられているwp-includes/widgets.phpを調査してみました。
ウィジェットを表示するdynamic_sidebar関数を手がかりに辿って行き、get_settingsというメソッドにたどりつきました。global宣言で変数を使い回しまくっているのですごくわかりづらいです。しかもメソッドの説明も不完全だし…。そこはおいといて、
function get_settings() { $settings = get_option($this->option_name); if ( false === $settings && isset($this->alt_option_name) ) $settings = get_option($this->alt_option_name); if ( !is_array($settings) ) $settings = array(); if ( !empty($settings) && !array_key_exists('_multiwidget', $settings) ) { // old format, convert if single widget $settings = wp_convert_widget_settings($this->id_base, $this->option_name, $settings); } unset($settings['_multiwidget'], $settings['__i__']); return $settings; }
get_settingsメソッドが何をしているかというと、$this->option_name というメンバ変数にwidget_textとかwidget_searchとか、ウィジェットの名称がはいっているようで、その名称をもとに、get_optionsという関数でデータベースからウィジェットのデータを取得しているようなのですね。コードはろうと思いましたが長いので最終的な出力の部分だけ掲載。
return apply_filters( 'option_' . $option, maybe_unserialize( $value ) );
maybe_unserializeという関数で、serializeされたデータをunserializeして出力するようです。で、ここでwidget_textの場合の出力を確認すると、falseが返されている!false!そりゃ存在しないかのように扱われるはずだ。
2つの環境のwp_optionsテーブルwidget_textの値を比較してみる
ただ、なんでfalseが返ってきているのかわからなかったので、テスト環境のwidget_textの値と本番環境のwidget_textの値を比較してみました。すると
// ■■■■はタイトル // ★★★★は本文 a:3:{i:3;a:3:{s:5:"title";s:15:"■■■■";s:4:"text";s:832:"★★★★";s:6:"filter";b:0;}i:4;a:3:{s:5:"title";s:9:"■■■■";s:4:"text";s:864:"★★★★";s:6:"filter";b:0;}s:12:"_multiwidget";i:1;} a:3:{i:3;a:3:{s:5:"title";s:15:"■■■■";s:4:"text";s:842:"★★★★";s:6:"filter";b:0;}i:4;a:3:{s:5:"title";s:9:"■■■■";s:4:"text";s:879:"★★★★";s:6:"filter";b:0;}s:12:"_multiwidget";i:1;}
本文部分のバイト数(★★★★の前のs:の後ろの数字)が違うことが判明。
ということは、移行側サーバーからしたら、「そのデータのバイト数だとserializeデータが示しているバイト数が違うので変換できねぇよ!」てことでfalseを返したんでしょうね。
ここまでしか調べていませんが、原因はサーバー間でのエンコード、改行コードの相違が怪しいかなぁ。
それにしてもWordPressのコアのコードはなかなかですね。せめて流れとか、関数が何をしているのかがわかる仕様なんかが公開されていると捗ると思うのですがね…。特に日本語の情報なんてほとんど無いようだし。コアの開発者?の皆さまはどうやって把握されているんでしょう?
追記
と、記事書き終わって気づいたー!
- エクスポートしたSQLデータをテキストエディタで開き、テキスト環境URLを本番環境URLに置換
これや!テキストウィジェットの中にURLが含まれているため、置換するとバイト数が変わってしまっていたのです。トホホ…。