ショートコードが勝手にpタグに囲まれてしまう場合がある。
例えば投稿記事で、
<h3>タイトル</h3>[my_shortcode /]
というふうにhタグの直後にショートコードを使った場合に発生する。hタグの次はpタグがこなくてはならないマークアップの法則にでも準拠してくれた結果なのだろう。出力されるHTMLは、
<h3>タイトル</h3><p>(ショートコードの出力)
となる。<p>だけを勝手に入れて</p>で閉じてくれないのが非常に困る。
このような場合は、
<h3>タイトル</h3><p>[my_shortcode /]</p>
と、最初から投稿記事にpタグを書いてしまうと解決する。出力されるHTMLは、
<h3>タイトル</h3>(ショートコードの出力)
となる。自分で書いたpタグまでもが消えているから不思議なのだが、解決したからいいか。
DBに連想配列を保存するには
DBテーブルのwp_optionsやwp_postmetaに配列っぽいデータが保存されているのを見ることがある。たとえば wp_postmetaでは_”wp_attachment_metadata”というキーに”a:5:{s:5:”width”;s:3:”145″;s:6:”height”;s:2:”74″;s:14:”hwstring_small”;s:23:”height=’65’ width=’128′”;s:4:”file”;s:35:”2010/…”というようなデータが保存されている。画象を添付した際のパスやサイズなどのメタデータである。
この形式を自分でも利用することができる。
例えばwp_optionsに保存するには、
INSERT INTO wp_options(option_id, blog_id, option_name, option_value, autoload) VALUES(null, 0, ‘my_messages’, maybe_serialize( $messages ), ‘yes’)
というようなSQLを実行すればよい。連想配列$messagesをシリアライズしたものをoption_valueにセットする。maybe_serialize()は、WordPressの関数である。
このデータを取得するには、SQLでSELECTして得た値を、
$messages = maybe_unserialize($result->option_value);
とすることで連想配列にセットされる。
ちょっとした情報を保存したいならプラグイン用にテーブルを作成するのではなく、 wp_optionsに保存する手段もあるのだ。Contact Form 7 のコードを見てて、この仕組みがやっと分かった。
Contact Form 7 でユーザーエージェント
WordPressを使う人なら誰もが知ってる「Contact Form 7」はお問い合わせフォームを設置するのにかかせないプラグインだ。カスタマイズ性の良さとAjaxの動作がいい。
この「Contact Form 7」を使ったお問い合わせの際に、ユーザが使っている環境が知りたいとの要望があった。Webサービスに関する問い合わせでは、ユーザがどのOSでどんなブラウザが使っているかが手がかりになる。問い合わせをしてくるユーザに限ってそれを把握していないことが多いため、自動で送って欲しいということだ。
「Contact Form 7」では、IPアドレスを取得する [_remote_ip]というタグは用意されているものの、ユーザーエージェントは用意されていない。「Contact Form 7」に用意されている”wpcf7_special_mail_tags”というフィルタを使ってタグを追加することができる。追加するには、テーマのfunctions.phpにショートコードとして記述するとよい。
[sourcecode language=’php’]
add_filter(‘wpcf7_special_mail_tags’, ‘my_special_mail_tags’,10,2);
function my_special_mail_tags($output, $name)
{
if(!isset($re_agent)){ $re_agent = $_SERVER[‘HTTP_USER_AGENT’]; }
if(‘my_user_agent’ == $name){ $output = $re_agent; }
return $output;
}
[/sourcecode]
これで、「Contact Form 7」のメッセージ本文で[my_user_agent]といタグを使えるようになる。$nameにタグ名が入ってくるので、タグ名で分岐するようにすればこの中で複数を設定することができる。
WordPressフォーラムのContact Form 7 ホスト取得を参考にした。
タイムゾーンがずれる
自作テーマで、時間に関連する部分に不具合がでた。WordPressを商用のCMSとして使っていて、イベントを表示するカレンダーで予約投稿の場合は「予定」と表示しておき、当日になったら「予定」が消えるというふうにしたかったのが、「予定」が消えるのが9時間遅くなるのだ。タイムゾーンの設定が変わってしまったのかと思ったけど、「UTC +9:00」になっているし投稿時間も正常だ。
テーマで現在時刻を取得するのに
date( ‘Y-m-d H:i:s’);
とやっていたのを、WorsPressの関数を使って、
current_time(mysql)
としたら直った。
WordPressの過去のバージョンで使ったことのあるコードを、バージョン2.9.2で流用したのが原因らしい。PHPの基本的な関数が使えなくなっていたとは、不便だ。もとからcurrent_time()を使うことが常識だったのかな?
もっともこの場合は、「当日」の判断をpost_dateではなくて、post_statusで判断すれば良かったのだ。
カテゴリー用のテンプレートファイル
WordPress 2.9よりカテゴリー用のテンプレートファイル category-slug.phpが用意されているようだ。いままでカテゴリごとに異なるデザインを表示するには、archive.phpで現在のカテゴリを取得して、if文で振り分けていた。category-termid.phpというテンプレートファイルもあったものの、サーバが異なるとtermidが同じとは限らないため利用しずらかった。slugであれば使ってみてもいいかな。
カテゴリー用のテンプレートファイルは以下の優先順で表示される。
1. category-slug.php
2. category-termid.php
3. category.php
4. archive.php
5. index.php
カテゴリーごとにHTML構造が変わらずCSSのみ変更したい場合は、テンプレートを分けずに、archive.phpの中で<div class=”スラッグ”>とし、スラッグごとにスタイルを当てる方法もある。
投稿内容を取得するget_post()
get_post()は投稿内容を取得する関数だ。投稿番号を指定することでsb_3_postsの内容が配列で返る。特定の記事を表示したい場合などに利用することができる。
パラメータには、数字ではなく参照値を指定しなくてはならない。
つまりget_post(投稿番号)ではなくて、
[sourcecode language=’php’]
$id=投稿番号;
get_post($id)
[/sourcecode]
とする。
はまった!
is_front_page()が使えなくなった
トップページかどうかの判断をis_front_page()で行っていた。これがあるときから、常にfalseになった。トップページかどうかでcssを切り替えているため、急にデザインが崩れて困った。is_home()で回避できるものの、腑に落ちないのでちょっと調べた。
直前に行っていた操作を思い出すうちに、管理画面で1ページに表示する最大投稿数を変更したことが原因らしかった。ためしに他のブログでもこの操作をしたら再現したのだ。しかし最大投稿数もとに戻したところで、is_front_page()はもとにはもどらなかった。
しかたがないので、Wordpressのコアソースでis_front_page()を追った。is_front_page()とは、’posts’ == get_option(‘show_on_front’) && is_home()というような意味らしい。この’show_on_front’というオプションがおかしくなっているようだ。MySql上ではではテーブルwp_optionsに設定されている。この値が空になっていたので手動で’posts’に書き直した。
is_front_page()は正常に戻ったように思う。
ググっても見当たらないけど、これはバグなのかな?
条件に応じてヘッダを変える
テンプレートのget_header()では、header.phpを読み込む。
条件に応じて別のヘッダを使いたい場合は、get_header(“2”)とパラメータを付けて呼ぶことができる。このときは、header-2.phpがよみこまれる。
フッタやサイドバーについても、同様だ。
表示条件に複数カテゴリを指定する
一覧の条件を指定するには、ループの直前にquery_postsでカテゴリや表示数などの条件を加えることができる。カテゴリ”ニュース”を指定するには、
[sourcecode language=’php’]
query_posts($query_string .”&category_name=news”);
[/sourcecode]
というようにスラッグで指定するといいのだが、スラッグはひとつしか指定することができない。複数(たとえば”英語”の”ニュース”)を指定する場合には、
[sourcecode language=’php’]
query_posts($query_string .”&cat=” .get_category_by_slug(‘news’)->term_id) .”,” .&cat=” .get_category_by_slug(‘english’)->term_id));
[/sourcecode]
というようにterm_idで指定するしかない。この場合はカテゴリが”英語”または”ニュース”の記事が表示される。両方の条件を満たす記事を表示する場合には、category__andというパラメータを使う。
[sourcecode language=’php’]
query_posts(array(‘category__and’=>array(get_category_by_slug(‘news’)->term_id, get_category_by_slug(‘english’)->term_id)));
[/sourcecode]
これではまだ”ニュース”の子孫カテゴリが拾ってこれない。”ニュース”の子孫と”英語”の両方を満たす記事を表示する場合は、ちょっとまわりくどいが以下の記述で実現した。
[sourcecode language=’php’]
query_posts(array(‘category_name’=>’news’, ‘category__and’=>array(get_category_by_slug(‘english’)->term_id),’showposts’=>5));
[/sourcecode]
もうちょっとスマートな方法はないかな?
投稿画面でカテゴリーをソートしない
管理画面の投稿画面にカテゴリーを選択するリストボックスがあり、いったんチェックをつけたカテゴリーは次回から上に表示される。CMSとして利用する場合はカテゴリーに2、3の階層を持たせることがほとんどなので、これをやられるとあとからカテゴリーの階層がわからなくなって困る。
この並べ替えをしない方法。
/wp-admin/includes/meta-boxes.php の
function post_categories_meta_box() から
wp_category_checklist() を呼ぶ箇所で、
[sourcecode language=’php’]
ID, false, false, $popular_ids) ?>
[/sourcecode]
となっているところに、引数を追加するとよい。
[sourcecode language=’php’]
ID, false, false, $popular_ids, ”, false) ?>
[/sourcecode]
6番目のパラメータがチェックされているカテゴリーを上にもってくるかどうかのフラグである。デフォルトでtrueとなっているのを、falseに指定する。5番目のパラメータは不明だが、デフォルトのNULLを指定しておく。こうすることで、カテゴリーのリストが常に同じ順番で表示される。
このようにWordPressの本体コードを修正すると、バージョンアップ時に上書きされてしまうのでおすすめできない。パラメータがあるということは、どこかに設定画面があるのだろうか?
とりあえず自分用にメモ。




Infinite Timeline
Google Maps Photo Gallery
Post Title Furigana
Posts Number Widget