PHP終了タグの件
今回の「サイト引越」に関連して移動後の動作確認でいろいろ不具合があった中で一番大きかったのはアップロードしたメディアが編集出来なくなったこと。メディア自体のアップロードも出来るしライブラリに表示されるし大丈夫と思って「移行判定会議」で「GO」を出した後で編集出来ないことが判明!サイトの閲覧には影響が無かったので旧サイトへの切り戻しは行わず新サイトで対策を考えることにしました。ちなみに「移行判定会議」の出席者は一人でしたw
ググってみるといくつか対策が出てきましたが、その中で一番多かったのが「class-wp-image-editor-gd.php」に「ob_end_clean()」を追加するというもの。
public function stream( $mime_type = null ) { list( $filename, $extension, $mime_type ) = $this->get_output_format( null, $mime_type ); while (@ob_end_clean()); /* この行を追加 */ switch ( $mime_type ) { case 'image/png': header( 'Content-Type: image/png' ); return imagepng( $this->image ); case 'image/gif': header( 'Content-Type: image/gif' ); return imagegif( $this->image ); default: header( 'Content-Type: image/jpeg' ); return imagejpeg( $this->image, null, $this->get_quality() ); } }
でもこのファイルはWordPressのコアファイルで「wp-includes」下にあり、ここを修正してもアップデートの度に再度修正する必要があります。そこでもう少しカスタマイズ側で対処する方法は無いのかと調べてみると、どうやらそもそもの原因がPHPの終了タグにあることが判ってきました。PHPの公式マニュアルには以下の記載があります。
「ファイル全体が純粋な PHPコードである場合は、ファイルの最後の終了タグは省略するのがおすすめです。 終了タグの後に余分な空白や改行があると、予期せぬ挙動を引き起こす場合があるからです。 余分な空白や改行のせいで PHPが出力バッファリングを開始し、その時点の内容を意図せず出力してしまうことになります。 」
そしておすすめの書き方がこちら。結構衝撃的でしょ?「終了タグを使い厳密に終わらないといけない」という幻想に取りつかれていました。言語仕様の発想が日本的でないw
<?php echo "みなさん、こんにちは"; // ... いろんなコードたち echo "最後のごあいさつ"; // PHP 終了タグを書かずに、ここでスクリプトを終わります。
カスタマイズ側での対処というのは、バージョンアップ等でコアが改変されても影響を受けないところで対処するってことなので、自分のコントロール下にある「子テーマ」内で対処出来ればベスト、ということになります。そこで子テーマの「functions.php」を以下のように修正することで、子テーマの支配下にあるいかなるPHPファイルからも「終了タグ」を取り除くことで対応することにしました。子テーマから呼ばれるコアも同様に扱われます。
<?php ob_start(); add_action( 'wp_enqueue_scripts', 'theme_enqueue_styles' ); function theme_enqueue_styles() { wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' ); wp_enqueue_style( 'child-style', get_stylesheet_directory_uri() . '/style.css', array('parent-style') ); } get_template_part( 'inc/template', 'tags' ); get_template_part( 'inc/breadcrumb' ); function fotografie_child_languages(){ load_theme_textdomain( 'fotografie', get_stylesheet_directory() . '/languages' ); } add_action( 'after_setup_theme', 'fotografie_child_languages' ); ob_end_clean();
コアファイルを書き換えるより子テーマで対応するこちらの方法がたぶん「王道」だと思うんだ。