WordPress, 親テーマfunctions.phpのaction, filterを子テーマでremove

WordPress3.0から使える親テーマ機能。
便利なんだけど、親テーマのfunctions.phpで設定されているactionやfilterを子テーマでremoveする方法が分からず悶々としてたけど、ようやく方法が分かりました。

本家Forum : [resolved] can i create child functions.php file for twentyten?
http://wordpress.org/support/topic/can-i-create-child-functionsphp-file-for-twentyten?replies=26

Adeptris さんによれば
after_setup_themeを使えば良いらしい。

/** Tell WordPress to run child_theme_setup()
when the 'after_setup_theme' hook is run.
*/
add_action( 'after_setup_theme', 'child_theme_setup' );
 
/** This function will hold our new calls and over-rides */
if ( !function_exists( 'child_theme_setup' ) ):
function child_theme_setup() {
 
}
endif;

関数 child_theme_setup にremoveを書けば対応できました。
感謝感謝です。

WordPress, 子テーマのための親テーマ作成の心構え – functions.php その2

親テーマ functions.php に add_filter されている関数を子テーマで変更することは困難を極めます。

読み込む順序が
1.子テーマ functions.php
2.親テーマ functions.php
になるからです。

これだと、いくら子テーマ functions.php で remove_filter しても意味がありません。
理論的には何らかの hook を使い最後の最後に remove_filter することは可能かもしれませんが、ワンクリック・インストールのWordPressらしくない解決方法に思えます。

親テーマの functions.php の関数は 全て functions_exists 判定 を入れることを必須条件にしてもらいたいものです。
そうすれば、子テーマでの変更はあっけないほど簡単にできます。
同名の関数を書けば良いだけですから。

Twenty Ten も一部の関数にしか判定が入っておらず不満が残ります。
というか、3.0対応テーマ作成の見本となるべきテーマなので早急に改善して欲しいです。

子テーマの子、孫テーマもありかな。

そうなると、配布テーマの functions.php の関数も 全て functions_exists 判定 が必須ですね。

update 2010-09-22
子テーマでremoveする方法があるので functions_exists が必須という訳では無さそうです。
でも、用意してくれてるとかなり嬉しい。

WordPress, 親テーマfunctions.phpのaction, filterを子テーマでremove

WordPress, wp_nav_menu+カスタムメニューのCSS設定

wp_nav_menu+カスタムメニューがナビゲーション・メニューを作るのに便利なことが分かってきた。
前回のPost : WordPress 3.x, wp_nav_menu コードを追ってみた

.menu の位置が状況によって変わるのでCSSの設定には注意が必要です。

Twentyten では次のように使われています。
header.php

wp_nav_menu( array( 'container_class' => 'menu-header', 'theme_location' => 'primary' ) );

この時のHTML出力は以下のようになります。

カスタムメニューを使用しない場合

Output(1行で出力されているのをインデントを付けています)

<div class="menu">
    <ul>
        <li >
            <a href="http://me.beginsprite.com/" title="ホーム">ホーム</a>
        </li>
    </ul>
</div>

menu オプションを指定していないので、ulwrap する div には class='menu' が設定されます。

Twentyten はデフォルトのページメニューを使用する場合 functions.php で 「ホーム」へのリンクを出力するように設定されています。

function twentyten_page_menu_args( $args ) {
	$args['show_home'] = true;
	return $args;
}
add_filter( 'wp_page_menu_args', 'twentyten_page_menu_args' );

カスタムメニューを設定した場合

<div class="menu-header">
    <ul id="menu-カスタムメニュー名" class="menu">
        <li >
            <a href="http://me.beginsprite.com/" title="ホーム">ホーム</a>
        </li>
    </ul>
</div>

class='menu' の位置が「カスタムメニュー」を使うと container タグ内 ul タグに設定されます。

配布テーマを作成する時は CSS 設定に充分な注意と配慮が必要になるでしょう。

WordPress 3.0のTwenty Tenのループ出力, loop.phpとget_template_part

Twenty Tenのループ出力は loop.php に集約されて書かれていて、loop.php を呼び出す部分は 3.0 から登場した関数 get_template_part が使われています。

関数リファレンス/get template part
Function Reference/get template part

使い方

<?php get_template_part( $slug, $name ) ?>

[編集] パラメータ
$slug
(文字列) (必須) 一般テンプレートのスラッグ名
初期値: なし
$name
(文字列) (オプション) 特定テンプレートの名前
初期値: なし

用例

[編集] 子テーマで loop.php を使用する
テーマフォルダが wp-content/themes で、親テーマが twentyten で、子テーマが twentytenchild の場合、この例はファイルを順に PHP require() します。

  1. wp-content/themes/twentytenchild/loop-index.php
  2. wp-content/themes/twentytenchild/loop.php
  3. wp-content/themes/twentyten/loop-index.php
  4. wp-content/themes/twentyten/loop.php
<?php get_template_part( 'loop', 'index' ); ?>

用例を見ると、関数 get_template_part は今まで include, require としていた部分を置き換えてくれるようです。

index.php には以下のように書かれています。

<?php
/* Run the loop to output the posts.
 * If you want to overload this in a child theme then include a file
 * called loop-index.php and that will be used instead.
 */
 get_template_part( 'loop', 'index' );
?>

子テーマでカスタマイズしたいときは、loop-index.php を子テーマに作れば良いってことになります。
これってかなり便利そうな気がする。

これからはテーマで include, require が書いてあるとイケテないってことになりますね。

get_template_part は関数 locate_template を使い最後は関数 load_template でロードすべきファイルを require_once します。

general-template.php

// @since 3.0.0
function get_template_part( $slug, $name = null ) {
	do_action( "get_template_part_{$slug}", $slug, $name );
 
	$templates = array();
	if ( isset($name) )
		$templates[] = "{$slug}-{$name}.php";
 
	$templates[] = "{$slug}.php";
 
	locate_template($templates, true, false);
}

theme.php

// @since 2.7.0
function locate_template($template_names, $load = false, $require_once = true ) {
	if ( !is_array($template_names) )
		return '';
 
	$located = '';
	foreach ( $template_names as $template_name ) {
		if ( !$template_name )
			continue;
		if ( file_exists(STYLESHEETPATH . '/' . $template_name)) {
			$located = STYLESHEETPATH . '/' . $template_name;
			break;
		} else if ( file_exists(TEMPLATEPATH . '/' . $template_name) ) {
			$located = TEMPLATEPATH . '/' . $template_name;
			break;
		}
	}
 
	if ( $load && '' != $located )
		load_template( $located, $require_once );
 
	return $located;
}
 
// @since 1.5.0
function load_template( $_template_file, $require_once = true ) {
	global $posts, $post, $wp_did_header, $wp_did_template_redirect, $wp_query, $wp_rewrite, $wpdb, $wp_version, $wp, $id, $comment, $user_ID;
 
	if ( is_array( $wp_query->query_vars ) )
		extract( $wp_query->query_vars, EXTR_SKIP );
 
	if ( $require_once )
		require_once( $_template_file );
	else
		require( $_template_file );
}

よくわかんないのは get_template_partdo_action のとこ。
do_action( "get_template_part_{$slug}", $slug, $name ); だと引数3つだけど・・・

plugin.php

function do_action($tag, $arg = '')

だから3つ目は無視されるよね。
どういうことなんでしょう?
あと、なんのための do_action なのかなぁ。

WordPress 3.0, Twenty Ten Theme 1.1 登場で何が変わった??

WordPressを3.0にすると、テーマも自動アップデートできて便利。
数日前に標準添付の Twenty Ten が 1.1 だよ、「自動アップデート」する??なメッセージが出てたので[ポチ]っとしました。
でも、プラグインと違って Change Log が見つからなたったので、何が変わったのか分からず少々不安な気持ちにもなりました。

仕組み自体が始まったばかりなので色んなことがこれから良くなっていくとは思います。

同じことを思った人はいるみたいでした。
WordPress 3.0 Twenty Ten Theme Updated
ここに詳しく書かれていました。

Andrew Nacin さんが Forum で答えてるよ、ということらしいです。
Changes Twentyten 1.0 >> 1.1

trac に diff があるから見てみたら、とも書いてあります。
http://core.trac.wordpress.org/log/branches/3.0/wp-content/themes/twentyten/
view changes

style.css (73 diffs)
functions.php (1 diff)
loop.php (1 diff)
page.php (2 diffs)
languages/twentyten.pot (12 diffs)
editor-style.css (4 diffs)
header.php (1 diff)
attachment.php (1 diff)

syle.css は記述方法を揃えるために「改行」や「スペース」の変更とプロパティ設定順の変更がされているようです。
あと、いくつかのバグがFixされていました。
nav-menus.php メニューに関するもの。
attachment.php, style.css メディア表示に関するもの。
位かなぁー。
ほとんどがタイポや表記の統一をしようとしているようでした。
こうやってテーマも進化していくのはいいことだと思う。

で、やっぱりチェンジ・ログがあると便利だと思います。
次のアップデートの時にはあるといいな。

update 2010-07-25 16:28
@odessy さんがブログにまとめてくれてます。
Twenty Ten 1.1 の変更点とアップデートの注意点

moファイルをアップしなおさないとメニューが英語表記のままになっちゃってるんですね。
今から、アップロードしておこう。

update 2010-08-03
大きな変更が抜けてました。
title の出力部分が大幅に変わっています。
表示そのものは変わってませんが、1.0 の時は functions.php にオリジナル関数を書いて wp_titleadd_filter していたのが、1.1 では関数を廃止しコードをtitleタグ間へ直書きになっています。

header.php を子テーマへコピーしてカスタマイズしている場合は、1.1版をコピーし再度カスタマイズが必要になります。

これが、親・子テーマの限界なんだなぁ。
親テーマに大幅な変更が加えられると、改造した子テーマへ影響があるかどうか調べないといけない、しょうがないけど。。。

update 2010-08-11
WordPress 3.0.1 ja へアップグレードした方は Twenty Tenも言語ファイル(mo)付きなので改めてmoファイルをアップロードしなくていいです。