WordPress使うなら、PHPのエラーメッセージと仲良くなっておこう

WordpPress Advent Calendar 2015 6日目の記事になります。

何を書こうか色々と迷ったのですが、フォーラムの質問やSNSなどを見ていると、まだまだPHPのエラーメッセージが何を伝えているかを見ていない人が多いと感じたので、啓発の意味も込めてエラーメッセージについて書いてみることにしました。(WordPressというより単なるPHPの話になっている気がしますが、デザイナーさんとかブロガーさんとか、必要だと思われる人が多い気がするのでよしとしてください。

WordPressは、至極当たり前ながらPHPで動作していますね。テンプレートだけだと、HTMLも混ざっているので、あまり感じられないかもしれませんが、index.phpから始まって、処理が全て完了するまで、全てPHP上で動作しています。そして、PHPのお作法上間違っていたりすると、その間違っている箇所で処理が止まってしまいます。

このとき、WordPressのデバッグモードを有効にしておくと表示されるのがエラーメッセージです。
このエラーメッセージは、エラーを取り除くための非常に重要な情報が詰まっていて、エラーの種類と原因、発生した場所が必ず含まれています。また、特定のエラーの場合は、それの原因となる場所を教えてくれるものもあります。エラーメッセージを正しく理解すれば、何が原因でなのかが一目瞭然になり、解決の最短距離をとることができるのです。

まずは、エラーメッセージの構造から見ていきましょう。

Fatal error: Call to undefined function wp_http_validate_url() in /path/to/wordpress/wp-includes/some-script.php on line 123

Fatal error:
この部分は、エラーの程度を示しています。Fatal error は致命的なエラーとして処理がとまります。Warning や Notice の場合は、このエラーで処理がとまることはありません。

Call to undefined function wp_http_validate_url()
エラーの内容を示いており、この部分で何が発生したのかを知ることができます。

in /path/to/wordpress/wp-includes/some-script.php on line123
エラーが発生したファイル名と行数を示しています。

これだけ分かれば、少なくともどこを直せばよいのか分かりますよね。
英語なので、とっつきにくい部分はあるかもしれませんが、落ち着いてよく読んでみれば、大体把握できると思います。

フォーラムでよく登場する代表的なエラーメッセージの説明とよくある原因、対処法を挙げておきますので参考にしてみてください。

Fatal error: Call to undefined function some_function() in /path/to/wordpress/wp-includes/some-script.php on line 123

未定義の関数が実行されようとしたというエラーです。

よくある原因として、関数名のスペルミスやFTPでのファイルアップロードエラー、プラグインを停止などがあります。自分で記述したものであれば、まずスペルの再確認をしましょう。WordPressの関数自体で発生したときは、ファイルの存在確認や、コアファイルの上書きアップロードなどが有効です。

Fatal error: Maximum execution time of 30 seconds exceeded in /path/to/wordpress/wp-includes/some-script.php on line 123

phpの実行時間上限に達した場合に発生します。大きいファイルサイズの処理やサーバに負荷が掛かっている場合、APIなど外部とのやりとりで処理がつまっている場合などに発生しがちです。

Fatal error: Cannot redeclare some_function() (previously declared in /path/to/wordpress/wp-includes/another-script.php on line 456) in /path/to/wordpress/wp-includes/some-script.php on line 123

同じ関数名が定義されようとした場合のエラーです。previously declared で示されるファイルの場所が最初に定義された箇所を示しています。
プラグインとテーマで同名の関数が定義されていた場合などに発生します。

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 65484 bytes) in /path/to/wordpress/wp-includes/some-script.php on line 123

PHPのメモリー上限を超えてしまった場合に発生します。サーバのメモリ設定が低かったり、プラグインが多い、1ページに表示する記事が多すぎる場合などに発生しがちです。
プラグインの変更などで対応できない場合は、サーバのメモリ設定の変更を検討します。変更ができないサーバでは、メモリの多いサーバへの移転を検討してください。

Fatal error: require() [function.require]: Failed opening required '../another-script.php' (include_path='.:/usr/local/share/pear') in /path/to/wordpress/wp-includes/some-script.php on line 123

ファイルの読み込みに失敗した場合のエラーです。ファイルがサーバに正しくアップロードされているか確認します。

Parse error: syntax error, unexpected end of file in /path/to/wordpress/wp-includes/some-script.php on line 123

PHPの記述間違いがある場合のエラーです。単に記述間違いに場合や if や while などの入れ子が合っていない場合にも発生します。入れ子のエラーの場合は、エラーメッセージの行にエラーが含まれていない場合があるんので注意する必要があります。

Warning: Cannot modify header information - headers already sent by (output started at /path/to/wordpress/wp-includes/another-script.php on line 456:1) in /path/to/wordpress/wp-includes/some-script.php on line 123

送出済みのヘッダ情報を変更しようとした場合に発生するエラーです。
このエラー単体では処理は停止しませんが、大抵の場合、ログイン時や記事更新時のリダイレクト処理で発生し、真っ白になってしまいます。
output started 示される場所で送出がされているので、該当箇所に文字や空行がないか、ファイルの編集が BOM付きになってしまっていないか確認します。

多少なりとも、今まで忌避していたエラーメッセージを読んでみようという気になったのであれば、まずは第一歩というところです。根気よく取り組んでみてくださいね。

7日のWordpPress Advent Calendar 2015は、徳丸先生です。
昨今、WordPressは標的にされやすいので、セキュリティには十二分の配慮が必要です。
どのような内容になるか私も楽しみです。
WordPress Advent Calendar 2015に参加したかった人達の Advent Calendar 2015はというと、井村先生です。プラグイン作るときに考えるあれこれとは興味深い。

WordPress 3.7以上で簡単にメディア表示をアップロードしたユーザーのみに限定する

なんとも時が経つのは早いもので、ちょっとほっておいたら、ほぼ1年ぶりの更新になってしまいました。

つい先日、コードを見ていて気がついたのですが、メディアの一覧を取得する関数 wp_ajax_query_attachments に WordPress 3.7 から、ajax_query_attachments_args フィルターが追加されていることに気がつきました。(遅

	/**
	 * Filter the arguments passed to WP_Query during an AJAX
	 * call for querying attachments.
	 *
	 * @since 3.7.0
	 *
	 * @see WP_Query::parse_query()
	 *
	 * @param array $query An array of query variables.
	 */
	$query = apply_filters( 'ajax_query_attachments_args', $query );

このフィルターで受け取る値には、WP_Queryによるメディアの抽出条件が格納されており、受け取った値を変更することで抽出条件を自由に変更することが可能です。このフィルターを通った値は、そのままWP_Queryに渡っていきますので、WP_Query で指定可能なパラメータであれば、なんでも指定可能となっています。

これを踏まえて、メディアの表示をアップロードしたユーザーのみに限定する最新で簡単な方法は、以下のコードとなります。

function display_only_self_uploaded_medias( $query ) {
	if ( $user = wp_get_current_user() ) {
		$query['author'] = $user->ID;
	}
	return $query;
}
add_action( 'ajax_query_attachments_args', 'display_only_self_uploaded_medias' );

このコードの方が以前よりも簡単ですし、間違いのないものですから、是非ともこちらを使うようしてくださいな。

WordPressのタイトル入力欄のプレースホルダー「ここにタイトルを入力」を register_post_type で指定する方法

カスタム投稿タイプを利用する場合に、件名の初期値が(プレースホルダーなんて洒落た言い方しますよね。)「ここにタイトルを入力」だと、わかりにくいケースってありませんか?

そうです。こいつです。

title_placeholder-default

このテキストを変更する方法は、enter_title_here というフックを使って、投稿タイプ毎に変更できるようになっています。

参考)
ここにタイトルを入力 を変更する | WordPress

だがしかし!

register_post_type のパラメーターには、うんざりするほど、labels の指定があるのに、このタイトル欄のプレースホルダーの指定がないのは、おじさん納得できません。

というわけで、register_post_type の labels に enter_title_here を指定すれば、プレースホルダーに反映されるようにしてみたいと思います。

“WordPressのタイトル入力欄のプレースホルダー「ここにタイトルを入力」を register_post_type で指定する方法” の続きを読む

WordPress 4.0 で言語パッケージがインストールされない原因を探ってみた

某環境にて、テストで WordPress 4.0(ベータ版)をインストールしてみたのですが、最初の言語選択で日本語を選んだ場合、本来なら

step-0-ja

と日本語表示になるのに

step-0-en

と英語のままとなってしまう現象がありました。

この原因を探っていったところ、ファイルのダウンロードが有効かどうかを調べるチェックの過程で実行される get_filesystem_method が原因であることが分かりました。

具体的には、問題なく動作する環境では、この関数の返り値が direct であるのに対し、失敗する環境では、ftpext が返ってきます。

この違いは、関数内の以下のコードによります。

$context = trailingslashit($context);
$temp_file_name = $context . 'temp-write-test-' . time();
$temp_handle = @fopen($temp_file_name, 'w');
if ( $temp_handle ) {
if ( getmyuid() == @fileowner($temp_file_name) )
$method = 'direct';
@fclose($temp_handle);
@unlink($temp_file_name);
}

コードの内容を簡単に説明すると、$context (インストール時は wp-contentディレクトリのパス)に、検証用の一時ファイルを作成し、そのファイル所有者と、getmyuid 関数で、PHP スクリプト所有者が同一かどうかのチェックを行っています。
このチェックが失敗(所有者が異なったり、ファイルが作成できなかった)した場合、$method に direct が代入されず、ftpext が返ってしまって、最終的に言語ファイルがダウンロード失敗に繋がります。

では、どうすれば良いかというと、検証用の一時ファイルはPHPが作成するため、PHPの実行ユーザーとなります。getmyuid 関数で返るPHP スクリプトの所有者は、インストール時の起動スクリプトである wp-admin/setup-config.php のファイル所有者ですので、これらを同一にすることで解消することができます。

つまり、対処方法は、PHPの実行ユーザーか、setup-config.php のファイル所有者を変えるかのいずれかになります。
ただし、この操作は、サーバー管理者レベルの権限が必要になるため、結構対応が難しいかもしれません。特に共用のレンタルサーバーとかでは。

この現象、結構発生する環境も多いのではないかと思っていて、ちょっと危惧しています。

リリースされてないけど WordPress 4.0 対応(になるかもしれない)プラグインを作ってみた

インストール時の言語選択
インストール時の言語選択

WordPress 4.0 の beta1 が先日発表されましたね。beta1以降は、バグフィックスのみとなり、新しい機能などは盛り込まれないので、よほど致命的なバグがない限り、ほぼこのままということになるでしょう。

どこらへんが変わったかは、おでさんの「WordPress 4.0 ファーストプレビュー」を見てもらうとして、なんと言っても、表示言語をインストール時に選択することで、言語専用のパッケージが基本的に不要になる(残るのかな)ことが一番の変わった点だと思います。

これは、インストール時にインストールするバージョンに対応した翻訳ファイルのリストをオンラインで取得して表示し、選択した言語の翻訳ファイルをインストール時にダウンロードして適用するような仕組みになっています。

select-wplang

また、「一般設定」画面において、マルチサイトには以前から存在していた「サイトの言語」の選択がシングルインストールにおいても利用できるようになり、インストール済みの言語を選べるようになっています。

で、1つ気になったのが、せっかくオンラインから翻訳ファイルを入手する仕組みがあるのに、インストール時しか言語を入手するインターフェースがなさそうだということです。

幸い 4.0 をインストールする際に利用される wp-admin/setup-config.php には、翻訳ファイルの取得やインストール方法も書いてあったので、これを参考に管理画面から翻訳ファイルを追加できるプラグインを作ってみました。

https://github.com/jim912/WP-Language-Plus

wp-lang-plus

added-langs

追加したい言語にチェックを入れて、下部の Install ボタンをクリックすると、翻訳ファイルを追加できるようになっています。