【WordPress】プラグイン Smart Custom Fields でカスタムフィールドを半自作する
あすリリースの『キンシオ the DVD 17号を行く』が待ち遠しくてしょうがない神奈川県民の kagata です。国道17号ではどんな百景に出会えるのでしょうか。楽しみです。
さて、今回は WordPress の悩みの種であるカスタムフィールドのお話です。サードパーティのプラグインでフィールド定義を設定・管理するのはお手軽ではあるものの、再利用やバージョン管理にひと手間かかってしまいます。一方、自力でいちからコードを書いてカスタムフィールドを実装するのは、かなり複雑なコードを書いていく必要があってこれまたたいへんです。
そんな中、カスタムフィールドを提供するプラグイン「Smart Custom Fields」に注目の新機能が追加されました。この機能を使うことで、プラグインでカスタムフィールドをお手軽に実装できる恩恵を受けつつ、取り回しがしやすいコードベースでフィールドを定義することができます。たいへんありがたいなあ、助かるなあと個人的に思ったのでここにご紹介します。
WordPress のカスタムフィールド実装って悩ましいですよね
振り返れば、これまで数々のカスタムフィールドプラグインにお世話になってきました。若干の浮気を除いて、だいたい次のような道をたどっています。
なつかしの(今も開発中!)Custom Field Template →カスタム三兄弟を一括管理できる Types →ループフィールドが無料でついてくる Custom Field Suite
WordPress のカスタマイズにはカスタムフィールドプラグインが欠かせません。カスタムフィールドの自力での実装がいかにめんどくさいかは WordPress Codex のサンプルコードをご参照ください。これだけがんばって、ようやくテキスト入力欄が追加できるのです…。
これだけのコードを書く作業量を圧縮し、さらにファイルアップロードやループ、記事間の関連づけなど高機能なフィールドも提供してくれるカスタムフィールドプラグインですが、自力実装と比べるとデメリットもあります。
1)バージョン管理が難しい
自力でコードを書いたカスタムフィールドなら、そのコードをバージョン管理システムにコミットしていけばそのままバージョン管理ができます。しかし、多くのカスタムフィールドプラグインはフィールド定義をデータベースで管理しており、バージョン管理がすぐにはできません。
2)再利用が難しい
上と同じような事情で、カスタムフィールド設定の再利用も困難です。
一部のカスタムフィールドプラグインは XML などで設定のインポート・エクスポートができる機能を備えています。まったく同じ設定であればこういう方法で再利用できそうですが、ちょっと変更を加えて…となるとエクスポート結果の書式を調べないといけなかったりして、管理画面から操作したほうが早いなんてことになります。
3)管理画面の操作が意外に難しい・説明しづらい
たまーにあるのが「カスタムフィールドプラグインを設定したけどうまくいかないので教えて!」という依頼。画面を見ながら説明できればいいんですが、離れたところからメールで質問を受けたりすると、文面で GUI の説明をするのがたいへんなことがあります。リモートでのやり取りなら、画面操作の説明よりもコードレビューのほうがやりやすいですよね。
4)プラグイン管理画面の仕様を離れたカスタマイズができない
初めて手がけた WordPress カスタマイズ案件に「カスタムフィールドのデフォルト値を動的に設定する」という要件がありました。そんな設定ができるカスタムフィールドプラグインがあればよかったのですが、見つからなかったので自力で実装しました。今思えば、初の案件にしてはずいぶんな冒険をしたものです(遠い目)。
Smart Custom Fields 1.2の新機能:smart-cf-register-fields フィルターフック
そんなわけでもやもやを抱えていたわたしの元に、このほど福音がもたらされました。
Smart Custom Fields でカスタムフィールドの定義を Git で管理できるようになりました! | モンキーレンチ
Git で管理できるようになったというのは、つまりプラグインが利用するフィールド定義をデータベースでなく PHP のコードで持つことができるようになったということです。PHP で書いたフィールド定義を smart-cf-register-fields
フィルターフックでプラグインに引き渡すというしくみになっています。
上記記事の表題では上に上げたデメリット1)バージョン管理の問題が解決できる点がフィーチャーされています。が、これでわたしが抱えていた2)再利用問題と3)管理画面の説明問題も同時に解決できるというわけで、幅広いメリットがあるすばらしい新機能だと感じています。
カスタムフィールドを半自作しよう - 管理画面をこえて -
プラグインの設定をコードで持つだけなら、形式としては JSON や XML などの選択肢もあるだろうと思います。しかし Smart Custom Field は PHP の配列とコールバック関数でプラグイン設定を管理するという、言ってみれば低級な API を提供する方法を取っています。
これをうまく生かせば、Smart Custom Field 管理画面からは作れないようなカスタムフィールドも実現できます。4)プラグイン仕様の制限問題をクリアして、思いどおりのカスタムフィールドを作れる可能性について考えてみました。
投稿タイプと投稿 ID による条件分岐
smart-cf-register-fields
フィルターフックからは投稿タイプ名と記事 ID を引数として受け取ることができます。これらを使って、メタボックスを表示する条件を制御できます。まずは、Smart Custom Fields 管理画面でも設定できるような条件を作ってみましょう。
function example_add_meta_box( $settings, $post_type, $post_id ) {
// 「投稿」と「固定ページ」にのみメタボックスを追加する
// ※条件が否定(メタボックスを追加しない条件)になっていることに注意
if ( !in_array( $post_type, array( 'post', 'page' ) ) ) {
return $settings;
}
// かつ、投稿 ID が1~99の記事にのみメタボックスを追加する
if ( $post_id >= 100 ) {
return $settings;
}
// 以降、通常のメタボックス追加ロジック
$Setting = SCF::add_setting( 'meta_box_example', 'メタボックスの例' );
$Setting->add_group( 'group_example', false, array(
array(
'name' => 'custom_field_example',
'label' => 'カスタムフィールドの例',
'type' => 'text',
'default' => '初期値の例',
),
) );
$settings[] = $Setting;
return $settings;
}
add_filter( 'smart-cf-register-fields', 'example_add_meta_box', 10, 3 );
これを踏まえて、管理画面からは作れないような表示条件を設定してみます。
こんなのとか。
// 自作のカスタム投稿タイプにはタイプ名の接頭辞に 'my_type_' をつけている。
// これら自作の投稿タイプにのみメタボックスを追加する。
// こうしておけば、投稿タイプを将来追加したときにも設定変更がいらないので便利。
if ( strpos( $post_type, 'my_type_' ) === false) {
return $settings;
}
こんなのとか。
// 投稿 ID がキリ番ならば投稿者からひとこともらいたい。
// 専用のメタボックスを追加しよう。
if ( $post_id % 100 !== 0 ) {
return $settings;
}
いろいろ頭を使えば、管理画面が提供する以上の柔軟なコントロールができそうですね。
デフォルト値と注記の動的設定
フィールドの設定が PHP の配列であることに注目すると、配列の中身を動的にしてやるというアイディアがわいてきます。管理画面からは静的な文字列しか設定できないデフォルト値と注記を動的に設定できることで、どんな機能が提供できるようになるか考えてみました。
最初に思い浮かんだのは多言語化。
$Setting->add_group( 'group_example', false, array(
array(
'name' => 'custom_field_example',
'label' => 'カスタムフィールドの例',
'type' => 'text',
// 日本語環境では「WordPress へようこそ!」に翻訳される
'default' => __( 'Welcome to WordPress!' ),
),
) );
現在時刻から動的に選択肢を出力するなんてのも、よくありそうです。
$year = intval(date('Y'));
$Setting->add_group( 'group_example', false, array(
array(
'name' => 'select_example',
'label' => 'セレクトな例',
'type' => 'select',
// プルダウンで今年、1年後、5年後のいずれかの西暦年を選択させる
'choices' => array( $year, $year + 1, $year + 5 ),
),
) );
このほか、データベースの内容から選択肢の出しわけをしたり、あるいはランダムにしてみたり、PHP でロジックが書ければなんでもできてしまいます。
おまけ:wp-config.php にフィールド定義を記述する
上記のコードはテーマの functions.php のほか wp-config.php に記述しても同じように動作しました。テーマの切り替えでフィールド定義が消えてしまうと困る場合は、wp-config.php に記述することをおすすめします。
おまけに追記:mu-plugins ディレクトリ
興味深いブコメをいただきました。ありがとうございます。
【WordPress】プラグイン Smart Custom Fields でカスタムフィールドを半自作する | バシャログ。フィールド定義を記述する場所は wp-config.php よりも mu-plugins のほうが適しているように思います。 https://codex.wordpress.org/Must_Use_Plugins
2015/03/25 22:14
ためしに、Smart Custom Fields のフィールド定義を書いた PHP ファイルを wp-content/mu-plugins/ の下に置いてみたところ、これまた問題なく動作しました。WordPress 本体の設定とプラグイン個別の設定とを分けて管理できるという点では、確かにこちらのほうがすっきりしそうですね。
mu-plugins ディレクトリに設置した PHP ファイルを WordPress 本体が自動でインクルードするという機能を今まで知らなかったので、少し調べてみました。この機能はかつて WordPress とは別のアプリケーションとして存在していた複数ユーザー対応版の WordPress MU から移植されたものだそうです。接頭辞 "mu-" はその名残なんですね。もともとは後方互換のための機能だったので将来廃止されるかもしれないという話が各所で見られましたが、コアのソースコード内のコメントなどを見る限りすぐに廃止されそうな気配はないようです。
おまけ:CMB2ライブラリ
カスタムフィールドをコードベースで簡単に構築するためのツールとしては、CMB2というライブラリもあります。こちらは単体で WordPress プラグインとして動作するものではなく、自作のテーマやプラグインに直接インクルードして使うものです。
独自のプラグインにカスタムフィールドを組み込んだり、WordPress をフレームワークにしてアプリケーションを開発したりするようなシチュエーションでは、こういうものも便利そうです。が、テーマのカスタマイズとプラグインの導入で Web サイトを立ち上げるような案件では、Smart Custom Fields のほうが気軽に使えそうですね。
まとめ
プラグイン Smart Custom Fields の力を借りながら、WordPress のカスタムフィールドを柔軟に実装する方法について検討しました。これからの WordPress カスタマイズに新しいスタイルを提供するツールになるのではと期待しています。
この記事では Smart Custom Fields のバージョン1.2で追加された新機能をご紹介しましたが、執筆中に早くもバージョン1.3がリリースされました。開発者のキタジマタカシさんはじめ、世界の WordPress プラグイン開発者のみなさまに感謝。