今回の WordPress バグですが、
またまた、カスタムヘッダーを利用する際のバグ紹介です。
( 解説に使用している WordPress ソースコードは WordPress 3.9 です )
【バグ確認バージョン】
WordPress 3.9
【前提条件】
add_theme_support 関数の第一パラメータに ‘custom-header’ を指定して
カスタムヘッダーを利用する指定をする際、
明示的にデフォルトヘッダーを指定していない
【現象】
管理画面[外観 - カスタマイズ] にて下記 Warning が発生
チラッと出て、他のレイヤーの下に隠れるので、気づかない方もいるかも・・・
/[WordPressディレクトリ]/wp-admin/custom-header.php on line 1248
Warning: array_merge(): Argument #2 is not an array in
/[WordPressディレクトリ]/wp-admin/custom-header.php on line 1268
【解消方法】
register_default_headers 関数にて、
明示的にデフォルトヘッダーを配列として登録する
管理画面からヘッダー画像を変更したり、ブログタイトルや
紹介文の文字色を変更できるようにさせるためには、
add_theme_support 関数の
第一パラメータに ‘custom-header’ を、
第二パラメータにデフォルトの挙動を指定する連想配列を与え、
カスタムヘッダーのサポートを有効にします。
/* カスタムヘッダー パラメータを指定して追加 */ add_theme_support('custom-header', array( 'default-image' => get_template_directory_uri() . '/images/header_photo-green.jpg', // デフォルトヘッダー画像 'random-default' => false, // ヘッダー画像をランダム表示するか 'width' => 986, // ヘッダー画像幅 'height' => 150, // ヘッダー画像高 'flex-width' => false, // 画像幅をフレキシブルにするか ・・・true:指定サイズに関係なくトリミング可能 / false:指定サイズに準拠した割合でのみトリミング可能 'flex-height' => false, // 画像高をフレキシブルにするか ・・・true:指定サイズに関係なくトリミング可能 / false:指定サイズに準拠した割合でのみトリミング可能 'default-text-color' => '464646', // ヘッダーテキスト文字色 'header-text' => true, // ヘッダーテキストの表示制御可否 'uploads' => true, // ヘッダー画像アップロード可否 'wp-head-callback' => 'header_style', // ユーザ画面ヘッダーで、管理画面でのカスタマイズスタイルを適用するためのコールバック 'admin-head-callback' => 'admin_header_style', // 管理画面で、[外観 - カスタマイズ]をプレビューするためのコールバック 'admin-preview-callback' => 'admin_header_preview' // 管理画面で、[外観 - ヘッダー]をプレビューするためのコールバック ));
上記のように、‘default-image’ を指定しているにも関わらず、
「 管理画面[外観 - ヘッダー] 」 を表示すると、
/wp-admin/custom-header.php の get_default_header_images 関数にて、
Warning が発生します。
PHP のエラー表示で Warning を表示しない設定にしていたり、
表示していても、画面表示上はチラッと出て他のレイヤーの下に
隠れてしまうので、気づいていない方もいるかもしれません。
なぜこんなことになるのでしょう?
public function get_default_header_images() { $this->process_default_headers(); // Get the default image if there is one. $default = get_theme_support( 'custom-header', 'default-image' ); if ( ! $default ) { // If not, return $this->default_headers; // easy peasy. } $default = sprintf( $default, get_template_directory_uri(), get_stylesheet_directory_uri() ); $already_has_default = false; foreach ( $this->default_headers as $k => $h ) { if ( $h['url'] === $default ) { $already_has_default = true; break; } } if ( $already_has_default ) { return $this->default_headers; } // If the one true image isn't included in the default set, prepend it. $header_images = array(); $header_images['default'] = array( 'url' => $default, 'thumbnail_url' => $default, 'description' => 'Default' ); // The rest of the set comes after. $header_images = array_merge( $header_images, $this->default_headers ); return $header_images; }
実際に Warning を吐いているのは、1248行目と1268行目です。
「Invalid argument supplied for foreach() in ・・・ on line 1248」
「array_merge(): Argument #2 is not an array in ・・・ on line 1268」
メッセージから、いずれも配列操作に関する argument の
Warning であることが分かります。
ここで操作している配列は、$this->default_headers です。
では、$this->default_headers はどこで初期化されているのでしょう?
$this は自身のクラスインスタンスを示す疑似変数ですので、
default_headers で custom-header.php を検索してみます。
ぬ?
ないではありませんか! 初期化するコードが!
/** * Holds default headers. * * @var array * @since 3.0.0 * @access private */ var $default_headers;
43行目に変数の宣言はありますが、配列としての宣言ではありません。
では、どこで代入があるのでしょう?
/** * Process the default headers * * @since 3.0.0 */ function process_default_headers() { global $_wp_default_headers; if ( !empty($this->headers) ) return; if ( !isset($_wp_default_headers) ) return; if ( is_array( $this->default_headers ) ) { return; } $this->default_headers = $_wp_default_headers; $template_directory_uri = get_template_directory_uri(); $stylesheet_directory_uri = get_stylesheet_directory_uri(); foreach ( array_keys($this->default_headers) as $header ) { $this->default_headers[$header]['url'] = sprintf( $this->default_headers[$header]['url'], $template_directory_uri, $stylesheet_directory_uri ); $this->default_headers[$header]['thumbnail_url'] = sprintf( $this->default_headers[$header]['thumbnail_url'], $template_directory_uri, $stylesheet_directory_uri ); } }
261行目で $_wp_default_headers を代入しています。
しかし、$_wp_default_headers は249行目で global 宣言されています。
なんてこった・・・
このソース (custom-header.php) だけで完結しねぇ・・・ orz
で、結局、$_wp_default_headers も他のソースでも初期化されているふうはなく、
配列として明示的に指定してやることをやってそうな関数は、
theme.php の register_default_headers 関数。
/** * Register a selection of default headers to be displayed by the custom header admin UI. * * @since 3.0.0 * * @param array $headers Array of headers keyed by a string id. The ids point to arrays containing 'url', 'thumbnail_url', and 'description' keys. */ function register_default_headers( $headers ) { global $_wp_default_headers; $_wp_default_headers = array_merge( (array) $_wp_default_headers, (array) $headers ); }
よって、解消方法としては、この (register_default_headers) 関数を使って、
明示的に、デフォルトヘッダ画像を(配列として)エントリしてやればよさそうです。
register_default_headers(array( 'photo-green' => array( 'url' => '%s/images/header_photo-green.jpg', // ヘッダー画像のアドレス 'thumbnail_url' => '%s/images/thum_photo-green.jpg', // ヘッダー画像のサムネイルのアドレス 'description' => '木漏れ日' // ヘッダー画像の説明や日本語名など(省略可) ), 'photo-sky' => array( 'url' => '%s/images/header_photo-sky.jpg', 'thumbnail_url' => '%s/images/thum_photo-sky.jpg', 'description' => '青空' ), 'photo-tunnel' => array( 'url' => '%s/images/header_photo-tunnel.jpg', 'thumbnail_url' => '%s/images/thum_photo-tunnel.jpg', 'description' => 'トンネル' ), 'texture-green' => array( 'url' => '%s/images/header_texture-green.jpg', 'thumbnail_url' => '%s/images/thum_texture-green.jpg', 'description' => '緑のプリント基盤' ), 'texture-blue' => array( 'url' => '%s/images/header_texture-blue.jpg', 'thumbnail_url' => '%s/images/thum_texture-blue.jpg', 'description' => '青い蜂の巣' ), 'texture-yellow' => array( 'url' => '%s/images/header_texture-yellow.jpg', 'thumbnail_url' => '%s/images/thum_texture-yellow.jpg', 'description' => '黄色いビームライン' ) ));
register_default_headers 関数へ食わせるパラメータは、
必ずしも複数のデフォルト画像を用意する必要はありませんが、
連想配列の多次元配列として与えてやる必要があります。
(上記、7行目から31行目はなくても大丈夫ということ)
なんだかなぁ・・・
どうなんだろう、このバグ・・・雑だなぁ
私が発見したときには未だ解決してませんでしたけど、
日本語版でも英語版でもフォーラムで話題に挙がったみたいですね。
このバグ・・・
> WordPress フォーラム 日本語:エラー ヘッダー画像関連?
> php problems with responsive on WordPress 3.9