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

子テーマは親テーマ設定をオーバーライドしながらカスタムできます。
テンプレートもCSSもこれで設定可能です。

ただ、現在の仕組みでは functions.php はオーバーライドはできず、子テーマの functions.php include の後に、親テーマの functions.php が include されます。

CodeX : 子テーマ

functions.php の使用方法

style.css と違い、functions.php は同名ファイルでオーバーライドできません。その代わり、親の functions.php に追加して読み込まれます。正確にいうと、親テーマの functions.php の直前に読み込まれます。したがって、もし親テーマの functions.php で favicon_link() という関数があるとき、子テーマのfunctions.php で同名の関数があれば、子テーマの関数が使用されます。

この説明だと足りない気がするんだよなぁ。

もし親テーマの functions.php で favicon_link() という関数があるとき、子テーマのfunctions.php で同名の関数があれば、子テーマの関数が使用されます。

これだけだと誤解をうみそうな気がする…

関数が二重定義にならないように

同名関数を子テーマで設定すると、親テーマの functions.php のデキが悪いと PHP エラーになるはず。
エラーが出ないようにするには、親テーマの関数設定には if (function_exists()) {} をしてもらわなければなりません。

カスタムメニューの準備

WordPress 3.0 対応を謳うテーマは「親テーマ」として機能するような配慮が必要になります。
カスタムメニュー対応のための

register_nav_menus( array(
	'primary' => __( 'Primary Navigation', 'TEMPLATE名' ),
) );

を入れておいた方が親切でしょう。
その時は、グローバルナビに wp_nav_menu を使いましょう。

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

カスタムメニュー、カスタム投稿タイプ、子テーマなど機能が増えたWordPressへの配布テーマ作成は今まで以上の困難が待ち受けていると想像されます。

CSS で抜かり無く設定するのは大変そう。

親テーマ / 子テーマ は新しく始まった機能なので、ドキュメントが充分とは言えない気がします。
これからノウハウがたまっていくのでしょう。

これって親テーマ作る時の常識だよね、が出そろうのはこれからなんでしょうねぇ。

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.x, wp_nav_menu コードを追ってみた

WordPress 3.0 から追加された wp_nav_menu のコードを追ったオレメモ。
多分「カスタムメニュー」に関係あるはず。

WordPress.com 日本語ブログ : 新カスタムメニュー機能 (など)
WordPress.com Support : Menus

Function Reference/wp nav menu
trac : nav-menu-template.php

$defaults = array(
'menu'            => ,
'container'       => 'div',
'container_class' => ,
'container_id'    => ,
'menu_class'      => 'menu',
'menu_id'         => ,
'echo'            => true,
'fallback_cb'     => 'wp_page_menu',
'before'          => ,
'after'           => ,
'link_before'     => ,
'link_after'      => ,
'depth'           = 0,
'walker'          => ,
'theme_location'  => );

wp_nav_menufallback_cb の設定をしない時は wp_page_menu を使って出力するので Parameter は wp_page_menu の Parameter を追加して設定できます。

fallback_cb => wp_page_menu のデフォルト時は wp_nav_menu の Parameter で次のものは設定しても無視されるようです。
container_class, container_id, before, after, link_before, link_after, menu_id.

wp_nav_menu は「カスタムメニュー」を使用しない時は wp_page_menu を出力します。
このとき出力される ul タグを container オプションのデフォルト div でwrapします。
この div には menu_class オプションのデフォルト class='menu' が設定されます。
menu_class オプションは wp_page_menu を使っているときでも設定可能です。
複数のクラスを設定したい時は半角スペースを使い設定します。
Usage :
'menu_class' => 'menu main-menu navigation'

theme_location が重要なようですが、さてこれは何を指定すれば良いのでしょう?
コードを追っていくと

// nav-menu.php
function get_nav_menu_locations() {
	return get_theme_mod( 'nav_menu_locations' );
}
 
// theme.php
function get_theme_mod($name, $default = false) {
	$theme = get_current_theme();
 
	$mods = get_option( "mods_$theme" );
 
	if ( isset($mods[$name]) )
		return apply_filters( "theme_mod_$name", $mods[$name] );
 
	return apply_filters( "theme_mod_$name", sprintf($default, get_template_directory_uri(), get_stylesheet_directory_uri()) );
}

ということはこんな感じかなぁ。

apply_filters(theme_mod_nav_menu_locations, $mods['nav_menu_locations']);

で、何をやってるのかは???
おしえて、わかる人。

update

2010-08-25

コードの意味は良くわかりませんが、、、
カスタムメニューで登録したメニューをデフォルト設定にした時、”primary” にすることで wp_nav_menu で出力できるようです。

“primary” のほかにどんな設定値があるのかは以前不明です。

wp_nav_menumenu オプションを設定すると「カスタムメニュー」で登録したメニューを呼び出せます。
カスタムメニューを使うとタイトルへのリンクをパーマリンクを変更せずに名称を変更できます。

カスタムメニューはページ、カテゴリー、タグなどを混在させたメニューを簡単に作成できます。
テンプレート・タグを駆使してグローバル・ナビゲーションを作成したことのある方にはありがたい機能です。

Usage:

 'menu-header',
    'menu' => 'gnavi',
    'container_id' => 'menu-main-menu',
    'menu_class' => 'inazumatv-menu inazumatv',
    'link_before' => '<span>', 'link_after' => '</span>',
    'menu_id' => "menu-main-menu-nav",
    'theme_location' =>; 'primary', 'depth' => '1' )
 );

Output:

<div id="menu-main-menu" class="menu-header">
<ul id="menu-main-menu-nav" class="inazumatv-menu inazumatv">
	<li id="menu-item-ID" class="menu-item menu-item-type-custom current-menu-item current_page_item menu-item-home menu-item-ID">
            <a href="/"><span>Home</span></a></li>
	<li id="menu-item-ID2" class="menu-item menu-item-type-post_type menu-item-ID2">
            <a href="URL"><span>Title</span></a></li>
</ul>
</div>

外観 -> メニュー
で “gnavi” という名称のカスタムメニューを登録しています。

これはかなり便利そうです。
カスタムメニューは複数登録できそうなので、これからメニューを作る時は「カスタムメニュー」+ wp_nav_menu の組み合わせがステキです。

update 2010-08-25
タグに関してはカスタムリンクを使えばメニューに加えることも可能ですが、他と比べて「簡単に」ではないので削除しました。

WordPress, Tweet Buttonを使ってみた

TwitterがTweet Button を公開しています。
http://twitter.com/goodies/tweetbutton

tweet button

簡単にTweet Buttonが追加できるようなので早速WordPressサイトで the_contentadd_filter しました。

functions.php

function inazuma_content_after_tweetbutton ($content) {
	global $post;
	$tweet_button = '';
 
	if (is_single())
		$tweet_button = '<div class="alignleft post-tweet"><a href="http://twitter.com/share" class="twitter-share-button" data-count="vertical" data-via="YOUR TWITTWER ID">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script></div>';
 
	$content .= $tweet_button;
	return $content;
}
 
add_filter('the_content', 'inazuma_content_after_tweetbutton');

div class はお好みで。
plugin にしても良いかもです。
その内誰かが作ってくれるでしょう。

update
一覧画面でTweet Buttonを押すとその画面に表示されているカウンタが全てカウントアップされるようなので(?)singleの時だけ表示するようにコードを変更しました。

ページでも表示させるなら判定条件に is_page() を加えるとよいでしょう。

update
新しい Twitter「Tweet」ボタン
http://ja.blog.wordpress.com/2010/08/13/new-tweet-button/

WordPress.comでは早速機能追加されてますね。
プラグインもすぐに出るでしょう。

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 なのかなぁ。

MAMP, アップグレードのためのメモ

MAMPはダウンロードしたMAMPフォルダを単純にアプリケーションフォルダへコピーするだけでインストールが完了します。
そのため、旧ファイルはすべて上書きになるので以前のデータ、特にデータベースをバックアプしないと悲しいことが起きます。

DBデータのバックアップも単純な上書きコピーで行えるので、ダンプを取ってRestoreなどの手順はいりません。

旧MAMPフォルダのdbフォルダをフォルダごとバックアップします。
デスクトップなどへ移動すればいいでしょう。

新MAMPをダウンロードしアプリケーションへコピーします。
「置き換える」と警告がでてもそのまま続けて構いません。

コピー後にMAMPフォルダへバックアップしたdbフォルダをコピーします。
これも置き換えてください。

MAMPを起動すると「データベースをアップデート」する旨のメッセージがでます。

これで、旧DBデータを引き継いだMAMPアップグレードが完了です。

*この手順は自分のメモのために書いたものです。データを保証するものではありません。トラブルが発生しても保証はできません。作業される場合はオウン・リスクでお願いします。

update
MAMP ヘルプファイルに同じことが書いてありました。

Procedure 1 MAMP update
1. Rename the current program folder MAMP to MAMP_OLD
2. Load the installation image of MAMP from http://mamp.info and open it
3. Drag the MAMP folder from the installation image to your “Applications“ folder
4. Copy the directories “htdocs” and “db “ from your MAMP_OLD folder into the
MAMP folder. It contains your personal HTML files and database contents.
Overwrite the folders in the new MAMP folder
5. Check whether all data has been transferred correctly
6. The MAMP_OLD folder can now be deleted. You may however keep it, so you can
fall back to your original setup

Apacheのdocument folderを htdocs にしている時はこれも上書きコピーね。

MAMPをアップグレードする時 PEAR ライブラリもバックアップとるといいよ

IE8, textareaのwidthを%指定してはいけない

いけてないブラウザIE8textareawidth%指定すると、文字入力時に勝手にスクロールして入力しづらくなります。
ピコピコ動いちゃうんですよね〜。

ひどい話です。
リキッド・レイアウトはするなってことなんでしょう。

【対策】
下記のどれかを使うと解消されます。

widthpx指定する。
わかりやすいでしょ。

position: absolute; を指定する。

IE7 標準モードにする。

<meta http-equiv="X-UA-Compatible" content="IE=7">

HTML5, ネタ元をメモ

HTML5時代がヒタヒタと忍びよってそうなので、きたるべき時に備えてネタ元を記録。

ブラウザの適応度をテスト
The HTML5 test – How well does your browser support HTML5?

何が出来るかのデモ。ブラウザ対応表付き。
HTML5 Demos and Examples

webmonkey さんの解説
Building Web Pages With HTML 5 | Webmonkey | Wired.com

本家W3CのDraft
HTML5

ユー、飛び込んじゃいなよ(?)
DIVE INTO HTML 5

先生らしいっす
HTML5 Doctor, helping you implement HTML5 today

日本語でズバリそのもの
HTML5.JP

初めの一歩はここからでしょうか
HTML5についてのおさらい

拙著inazumatv.comブログでもまとめています
http://www.inazumatv.com/contents/archives/tag/html-5

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ファイルをアップロードしなくていいです。

WordPress 3.0, 子テーマのURLとパス

子テーマを使うとTEMPLATEPATH, get_bloginfo("template_url") は 親テーマのパス, URL を返します。

子テーマのURL, パスを知る方法はないものかとガサゴソしたら使えそうなのが見つかりました。

URL

get_stylesheet_directory_uri();

PATH

STYLESHEETPATH

get_stylesheet_directory_uri(); は使用しているテーマまでのURLを返してくれます。

STYLESHEETPATH は使用しているテーマまでのフルパスが設定されている定数です。

これを使うと子テーマまでのURL, パスがわかります。

update 2010-08-04
general-template.phpget_bloginfo を見ると子テーマの URL は取得できるようです。

// get_stylesheet_directory_uri(); と同じ
get_bloginfo('stylesheet_directory');

update 2010-08-11
子テーマのパスを知りたかったのは include, require したいからだったけど、get_template_part を使えば必要ないことがわかった。
WordPress 3.0のTwenty Tenのループ出力, loop.phpとget_template_part

update 2011-01-31
あれ〜。
TEMPLATEPATH が子テーマのパスを返してる。。
変わったんかなぁ?
Ver. 3.0.4 のお話。

get_bloginfo('template_url')

コアが変更になったんだ。
不便だもんね。