WordPressメモ
注意事項
情報が古すぎるので現時点では役に立たない可能性が大きいです。
はじめに
個人的なWordPress用のメモ一覧。
あとでミスを見つけることもあるので、こまめに書き換えると思う、たぶん。
2.6がリリースされた辺りから書きためているものなので、情報が古くなっていることもあると思う。それと同じことを実現するのにも、よりスマートに出来ることがあるかもしれない。ここに書かれていることは鵜呑みにしないこと。あくまで参考程度にとどめておくことをオススメする。コピペした結果何か起きても私は責任とらないのでそのつもりで。
メモの一覧
- pre_get_postsに関するメモ
メインクエリ(そのページに本来表示する内容)を変更する場合はquery_postsじゃなくてpre_get_postsフィルター使おうね、的なのを今更知ったのでメモっておく。
ちなみにサブクエリ(ブログのサイドバーに表示する「関連記事」みたいなのとか)の場合はget_posts使った方がいいらしい。
使い方
function my_posts_new($query){ //管理画面またはメインクエリじゃない場合は何もしない if(is_admin() || ! $query->is_main_query() ) { return; } //以下変更内容を記述 } //最後にadd_action add_action('pre_get_posts','my_posts_new');
変更内容の記述について
if ( $query-> [条件指定] ) { $query->[詳細な変更内容]; }
みたいに書く。以下記述例。基本的にget_postsで指定できる内容が指定できるみたい。if文の条件指定部分は動作しないものがあるみたい。
カテゴリページのみ1ページ毎の表示件数を15件にしたい
if ( $query->is_category() ) { $query->set('posts_per_page', '15'); }
トップページに投稿だけじゃなくカスタム投稿も含めた新着5件を表示したい
if ( $query->is_home() ) { $query->set('post_type', array('post', 'カスタム投稿名') ); $query->set('posts_per_page', '5'); }
- 生成するimg要素にtitle属性とわけのわからんclassが付与されていて気持ちが悪いのを何とかする
wp_get_attachment_imageとかが生成するimg要素にtitle属性とわけのわからんclassが付与されていて気持ちの悪い人用フィルタ。functions.phpに書いて使う。
function remove_title_from_image_attributes( $attr ) { if ( isset( $attr['title'] ) ) { unset( $attr['title'] ); } if ( isset( $attr['class'] ) ) { unset( $attr['class'] ); } return $attr; } add_filter( 'wp_get_attachment_image_attributes', 'remove_title_from_image_attributes' );
- 投稿に紐づいている画像のサムネイルを複数表示する
単純に1枚表示するだけだったら、「アイキャッチ画像」を利用すればいいけど、複数枚出したいとなるとそうはいかないので、以下の関数を利用する。
引数の$maxは表示枚数。デフォルトは-1なので全部。$sizeはサムネイルのサイズ。add_image_size()で定義したサムネイルの名前を指定する。foreach文の中でechoしてるとこが出力部分だから適当に書き換えれば好きなマークアップに変更できる。
function post_thumbs_gallery($max='-1', $size='thumbnail'){ global $post; $args = array( 'post_type' => 'attachment', 'numberposts' => $max, 'post_status' => inherit, 'post_parent' => $post->ID, 'post_mime_type' => 'image', 'orderby' => 'menu_order ID', ); $attachments = get_posts($args); if (is_array($attachments)) { foreach ($attachments as $attachment) { echo ''.wp_get_attachment_image($attachment->ID,$size).""; } } }
wp_get_attachment_imageが吐き出す、img要素の記述が気にくわなくて、どうにかした記憶があるんだけど、どうしたんだっけか。明日職場で確認しよう。
追記
ちなみに。
関数内にget_posts()が書かれているのでわかる人はわかると思うけど、$argsの中身を色々書き換えて、柔軟にファイルの呼び出しができる。
「post_mime_type」に「image/jpeg」とか指定すると、JPEG画像だけ呼び出せたり、「offset」を追加して「1」とか指定すると、最初の1つを除外して、2つ目の画像から表示したりもできる。
あとは、写真サイトで使うときなんかに、$args内にある「post_parent」を指定しないでこの関数をhome.phpで使うと、WordPress内にアップロードした全画像の中からX枚画像を表示とかできていいかもね。
- カテゴリ一覧でアクティブなカテゴリをハイライト表示させる
カスタム分類一覧を表示したいときのお話。いや、カスタム分類に限った話じゃなくて、通常のカテゴリにも当てはまる話なんだけどね。
以下、カスタム投稿「products」にカスタム分類「productcat」が設定されているものとして話を進める。
とりあえずこんな感じにsidebar.phpに記述すると
カスタム分類「productcat」の一覧が順不同リストとして表示される。
で、困るのが記事なりページなりが所属するカテゴリをハイライト表示させたいとき。
カスタム分類のアーカイブページでは該当するカテゴリのli要素に「
current-cat
」というclass属性値が自動的に振られるから、CSS書けば簡単にアクティブなカテゴリの表示を変更できる。ところが個別の記事ページでは「
current-cat
」ってclassが振られないので、どうしようこれ、みたいになって困る。というか困った。そこでだ。以下のようにして何とかした。
-
ID, 'productcat');
foreach ( $catinfos as $catinfo ) :
$mycat = $catinfo;
break;
endforeach;
wp_list_categories( 'taxonomy=productcat&title_li=¤t_category='.$mycat->term_id);
else:
wp_list_categories( 'taxonomy=productcat&title_li=');
endif;
?>
まず
if(is_singular('products') ) :~else:
と書いて、カスタム投稿「products」の個別記事ページとそれ以外で処理内容を分岐。「products」の個別記事ページ以外では普通に「productcat」一覧を出力させる。
問題は「products」の個別記事ページの方で、どうしようか悩んでたらCodexに都合のよさそうなパラメータが。「
current_category
」にカテゴリIDを記述することで、「現在表示されてるページのカテゴリは○○だ」と強制できるらしい。これを利用したのが
if(is_singular('products') ) :
内の記述部分で、まずはget_the_terms
関数で現在の記事が属する「productcat」情報を取得。配列でごちゃごちゃなってるのでforeach関数使って、記事が属する「productcat」の最初の1つだけを使う。必要な情報はカテゴリID(整数)なので当該連想配列の中の「term_id」を持ってくればOK。あとはwp_list_categories
関数にパラメータとして記述すればいいだけなので、あんな感じに書けば終了。上の書き方の欠点は複数のカスタム分類に所属している記事については、(たぶん)IDの若い方の情報しか得られないので、複数カテゴリに所属していても複数のリンクをハイライト表示できないところにある。パラメータ「current_category」には整数しか渡せないっぽいので、所属カテゴリすべてにclass「
current-cat
」をつけたいときはどうしたらいいんだろうか、と思ったり。- WordPress内の特定カテゴリにDigest認証をかける
テーマ内のfunctions.phpに以下の関数を記述。$redirect_noscript_urlには認証に失敗したときのリダイレクト先が入るみたい。下の例ではWordPressのHomeになる。
//Digest認証 function digest_auth($userArray) { $redirect_noscript_url = get_bloginfo( 'url' ); $realm = "Member Only"; $users = $userArray; $_SERVER[ 'PHP_AUTH_DIGEST' ] = stripslashes( $_SERVER[ 'PHP_AUTH_DIGEST' ] ); if (empty($_SERVER['PHP_AUTH_DIGEST'])) { header('HTTP/1.1 401 Unauthorized'); header('WWW-Authenticate: Digest realm="'.$realm. '",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"'); die(''); } else { // PHP_AUTH_DIGEST 変数を精査する if (!($data = http_digest_parse($_SERVER['PHP_AUTH_DIGEST'])) || !isset($users[$data['username']])) { header('HTTP/1.1 401 Unauthorized'); header('WWW-Authenticate: Digest realm="'.$realm. '",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"'); } } // 有効なレスポンスを生成する $A1 = md5($data['username'] . ':' . $realm . ':' . $users[$data['username']]); $A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']); $valid_response = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2); if ($data['response'] != $valid_response) { header('HTTP/1.1 401 Unauthorized'); header('WWW-Authenticate: Digest realm="'.$realm. '",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"'); die(''); } } // http auth ヘッダをパースする関数 function http_digest_parse($txt) { // データが失われている場合への対応 $needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1); $data = array(); preg_match_all('@(\w+)=([\'"]?)([a-zA-Z0-9=./\_-]+)\2@', $txt, $matches, PREG_SET_ORDER); foreach ($matches as $m) { $data[$m[1]] = $m[3]; unset($needed_parts[$m[1]]); } return $needed_parts ? false : $data; }
テーマ内のheader.phpに以下のように記述。$catArrayはDigest認証をかけたいカテゴリIDの配列。$userArrayはIDとパスの連想配列。例では2バイト文字列使ってるけど、実際に利用するときは1バイト文字で。
"パス1", "ユーザID2" => "パス2", ); digest_auth($userArray); endif; endif; ?>
使い方はBasic認証のそれと同じ。Basic認証よりもセキュリティ的に随分マシなので、サーバとUAが対応しているのであればこっちの方がいいと思う。っていうか、Basic認証を使う意味はあまりない。こちらもBasic認証版と同様に、サーバによっては動かないと思う。
参考記事 ((ほぼそのまま持ってきただけ。多謝。))
- WordPress内の特定カテゴリにBasic認証をかける
テーマ内のfunctions.phpに以下の関数を記述。$realmは認証名、$failed_textは認証に失敗した際に表示されるメッセージ ((きちんとしたHTMLを出力するようにしてもいいかも。あとは認証に失敗したときは別のページにリダイレクトさせるとか。))。
function basic_auth($auth_list,$realm="Restricted Area",$failed_text="認証に失敗しました"){ if (isset($_SERVER['PHP_AUTH_USER']) and isset($auth_list[$_SERVER['PHP_AUTH_USER']])){ if ($auth_list[$_SERVER['PHP_AUTH_USER']] == $_SERVER['PHP_AUTH_PW']){ return $_SERVER['PHP_AUTH_USER']; } } header('WWW-Authenticate: Basic realm="'.$realm.'"'); header('HTTP/1.0 401 Unauthorized'); header('Content-type: text/html; charset='.mb_internal_encoding()); die($failed_text); }
テーマ内のheader.phpの先頭に以下のように記述。$catArrayはBasic認証をかけたいカテゴリIDの配列。$userArrayはIDとパスの連想配列。例では2バイト文字列使ってるけど、実際に利用するときは1バイト文字で。
"パス1", "ユーザID2" => "パス2", ); basic_auth($userArray); endif; endif; ?>
上の例ではIDが1,2,3のカテゴリにBASIC認証がかかる。
あくまでBASIC認証だからセキュリティ的には微妙。特定のカテゴリを検索避けしたい時なんかには使える? DBと連携させてもいいかもしれない。サーバの環境によっては動作しないこともあるみたい。マニュアルによると、PHPがApacheのモジュールとして動いているときのみ可で、CGI版ではダメらしい。
参考記事 ((というかそのまま持ってきただけ。多謝。))
- WordPressが出力するファイルではない場所で、WordPressの関数を使いたい
WordPressの関数を使いたいファイルの冒頭で
と記述 ((当然そのファイルがPHPとして処理されないとアウト。拡張子にこだわる人は.htaccessで.htmlがPHPとして扱われるようにするといい。ただ、全HTMLをPHPとして処理されるようにするのはサーバへの不可とか考えると微妙だと思う。特定のファイルに限定するようにした方がいいかもね。))。「PATH」の部分には、そのファイルからwp-load.phpまでの相対パスを入れる ((「wp/wp-load.php」とか「../blog/wp-load.php」とか。))。それ以後はWordPressの関数が利用可能に。おそらく条件分岐タグなどは不可 ((というかどういう判定になるのか調べてない。))。
と書くことでも同様のことが可能だが、こちらはHTTPヘッダ内で404エラーとして処理されるようなので、前述のwp-load.phpを読み込んだ方がベター。
- 最新1日分の記事を表示する
posts "."WHERE post_status = 'publish' AND post_type = 'post' "."ORDER BY post_date DESC LIMIT $limit"; $posts = $wpdb->get_results($request); if($posts): $recent_date = date('Ymd',strtotime($posts[0]->post_date)); foreach ($posts as $post): $post_date = date('Ymd',strtotime($post->post_date)); if($post_date == $recent_date): setup_postdata($post); ?> //記事の表示内容を記述
以下、上の記述の簡単な説明。
- データベースから最新10件 ((ここで10件にしたのは、一日にどんなに更新したって10回はいかないだろう、という経験則から。1日100回更新することがある人は当然10じゃ足りないので$limitの値を適宜変更すること。))の投稿を取得して $posts にぶちこむ
- 最新の記事、すなわち $posts[0] の post_date を strtotime 関数と date 関数を使って「20081210」みたいな形式に変換して変数 $recent_date に格納
- foreach 関数使って $recent_date とその他の投稿データの日付を比較しつつ ((当然比較するための日付データも strtotime 関数と date 関数を使って形式変換しないとダメ。)) 、$recent_date と同じ日付の投稿データがあったら setup_postdata() したあとで the_title() やら何やらで表示
上記のコードをindex.php辺りに書くと、私のサイトのように最新1日分の記事がトップページに表示される。もっとスマートに出来るんじゃないかなぁ、とか思ったりもするので、各自頑張ってください(謎)。
- WordPress 2.8にしてからhead要素内に無駄な要素が増えてウザい件について
WordPress 2.8になってから、head要素内に勝手にナビゲーション用のlink要素なんかが挿入されるようになって、かなりウザかったので何とかした。必要なものは自分で書くから余計なことすんなっての。大きなお世話だバカ。
で、対処法。wp-includesディレクトリ内のdefault-filters.phpを覗いてみると、167行目辺りから下記のような記述がある。
add_action('wp_head', 'wp_enqueue_scripts', 1); add_action('wp_head', 'feed_links_extra', 3); add_action('wp_head', 'rsd_link'); add_action('wp_head', 'wlwmanifest_link'); add_action('wp_head', 'index_rel_link'); add_action('wp_head', 'parent_post_rel_link', 10, 0); add_action('wp_head', 'start_post_rel_link', 10, 0); add_action('wp_head', 'adjacent_posts_rel_link', 10, 0); add_action('wp_head', 'locale_stylesheet'); add_action('publish_future_post', 'check_and_publish_future_post', 10, 1); add_action('wp_head', 'noindex', 1); add_action('wp_head', 'wp_print_styles', 8); add_action('wp_head', 'wp_print_head_scripts', 9); add_action('wp_head', 'wp_generator');
で、こいつらがadd_actionされてるのでremove_actionすればいいんだけども、いくつか関係ないのがあるので排除。
add_action('publish_future_post', 'check_and_publish_future_post', 10, 1);
こいつはwp_headにaddされてないので無関係。
add_action('wp_head', 'noindex', 1);
こいつがなくなると管理画面「設定」内の「プライバシー」が上手く機能しなくなると思われるのでこれも除く。残りをremoveすればいいので、テーマディレクトリ内のfunctions.php内に下記のように記述すればOK。
remove_action('wp_head', 'wp_enqueue_scripts', 1); remove_action('wp_head', 'feed_links_extra', 3); remove_action('wp_head', 'rsd_link'); remove_action('wp_head', 'wlwmanifest_link'); remove_action('wp_head', 'index_rel_link'); remove_action('wp_head', 'parent_post_rel_link', 10, 0); remove_action('wp_head', 'start_post_rel_link', 10, 0); remove_action('wp_head', 'adjacent_posts_rel_link', 10, 0); remove_action('wp_head', 'locale_stylesheet'); remove_action('wp_head', 'wp_print_styles', 8); remove_action('wp_head', 'wp_print_head_scripts', 9); remove_action('wp_head', 'wp_generator');
remove_action関数の最後の引数の数字って何なんだろ ((軽く調べてみたら、前の数字がThe priority of the function、後ろの数字がThe number of argumentsとのこと。結局よく分からんな。))。なくてもいいかもしれない。あと必要に応じてremove_actionするものを減らせばいいと思う。「~がなくなった」とか何とかなるかもしれないし。
追記
この記事についたブコメに以下のようなものがあった。
wp_enqueue_scripts,wp_print_head_scripts,wp_print_styles,locale_stylesheet はremoveしない方が良いと思うんだ。大多数のプラグインがまともに動作しなくなるよ。
まぁ、たしかにそうなんだけど、そもそも私はプラグインによって勝手に挿入されるJavascriptやらCSSやらが好きじゃないんだよね。あまり複雑なプラグインを使ってないので、私のサイトには何の影響もない。こいつらを排除したところで管理画面に影響が出るわけでもないし ((で、合ってるよね?))、正直どうでもいい。
もちろん人によってremove_actionしちゃまずいものが出てくるだろうから、それは各自の裁量で適当に何とかして欲しいところ。何とかできない人については私の知ったところではないのでどうでもいい。
追記2
バージョンによってwp_headにadd_actionされる内容が結構変わるので注意。3.0.1では上の記述だとダメだと思う。例えば「adjacent_posts_rel_link」が「adjacent_posts_rel_link_wp_head」に変わっていたりとか。
- 特定のカテゴリ且つ特定のタグを持つ記事の抽出
$category_id, 'tag_slug__and'=>array($tag_slug), 'paged'=>$current_paged); query_posts($query); ?>
WordPressループの手前に書いておけばOKなはず。
query_posts関数の引数は文字列ではなく配列形式にする必要がある。また、クエリ内にpagedの値を入れないとページナビゲーション系が動作しない。
- ページのスラッグを取得
function get_page_slug($page_id) { $page = get_page($page_id); return $page->post_name; }
引数の$page_idはページのIDね。
- カスタムフィールドの内容を取得
function my_get_meta($key){ global $post; return get_post_meta($post->ID,$key,true); }
$keyはカスタムフィールドのフィールド名。値を取得するだけなので、そのまま表示したい場合はechoする。
- query_posts()を利用しつつ親カテゴリのアーカイブで子カテゴリの記事を出力する
カテゴリアーカイブ内の$catで取得できる値は親カテのIDだから、そのままquery_posts()に値を投げ込むと親カテと子カテの両方にチェック入れてない限り、親カテのアーカイブでは子カテの記事は表示されない。
よって、get_category_children()でその親カテに所属する子カテのIDを取得してquery_posts()に投げ込めば、子カテにしかチェック入れてない記事も親カテのアーカイブに表示させることができる。
補足。get_category_children()で取得できる値は文字列 ((たしか「/」区切りだったはず。))なので
split関数((split関数はPHP 5.3で非推奨になった模様))explode関数を使って配列形式にしてからquery_posts()に投げ込まないといけない。//子カテゴリのIDを配列で取得 function get_child_id_Array($parrentID){ $childcat = get_category_children($parrentID); if($childcat) { $childcat = explode('/',$childcat); array_shift($childcat); return $childcat; } else { return array($parrentID); } }
- 子カテゴリのIDから親カテゴリの情報を取得する
$childCat = get_category($cat); if ($childCat->parent) { $parentCat = get_category($cat->parent); }
カテゴリーアーカイブ内での使用を想定して$catと書いたけど、$catに子カテゴリのIDを入れれば別にどこでも使える。あとは
echo attribute_escape($parentCat->cat_name);
とかやればカテゴリ名を出力できたり、色々。var_dump($parentCat);
とかやって$parentCatの中身を出力してみると何が格納されてるのか分かりやすいと思う。$parentCatは配列なのでechoしただけじゃ中身をみられないので注意。- head要素内に前後の記事へのリンク要素を生成
function meta_link() { if(is_single()) { global $wpdb, $wp_query; $post = $wp_query->post; $prev_post = get_previous_post(); if($prev_post) { $prev_title = strip_tags(str_replace('"', '', $prev_post->post_title)); echo '' . "\n"; } $next_post = get_next_post(); if($next_post) { $next_title = strip_tags(str_replace('"', '', $next_post->post_title)); echo '' . "\n"; } } }
テーマ内のfunctions.phpに記述しておいて、適当な箇所で呼び出して使う。
- 特定のIDを持つ記事を除外する方法
query_posts( array(‘post__not_in’ => array(投稿ID) ); とかなんとかやって配列で除外したい投稿 ID を入れれば OK。当然、$query_stringの中身も入れないと特定記事を除いた全記事が出力されてしまう。
たとえば、カテゴリアーカイブでIDが1と3の記事を除外する場合。
$current_paged = intval(get_query_var('paged')); $query = array('cat' => $cat , 'post__not_in' => array(1,3) , 'paged' => $current_paged); query_posts($query);
- WP-Pagenaviを使わずにページナビゲーションを表示
「吟遊詩人の戯言 » ページナビゲーション機能を改版してみたり」より。
function bmPageNavi() { global $wp_rewrite; global $wp_query; global $paged; $paginate_base = get_pagenum_link(1); if(($wp_query->max_num_pages) > 1): if (strpos($paginate_base, '?') || ! $wp_rewrite->using_permalinks()) { $paginate_format = ''; $paginate_base = add_query_arg('paged', '%#%'); } else { $paginate_format = (substr($paginate_base, -1 ,1) == '/' ? '' : '/') . user_trailingslashit('page/%#%/', 'paged');; $paginate_base .= '%_%'; } $result = paginate_links( array( 'base' => $paginate_base, 'format' => $paginate_format, 'total' => $wp_query->max_num_pages, 'mid_size' => 5, 'current' => ($paged ? $paged : 1), )); echo '
- '."\n\t
- ".$result." \n
functions.phpに書いておいて使う。ul要素にするのが嫌だって場合は、最後のecho文を好みの出力形式に変えればいいと思う。
追記
WordPress 3.0.1 ((ひょっとしたらもっと前から?))を利用していて、query_posts関数のパラメータposts_per_pageで1ページ当たりの記事数を指定したときに、ページ送りが上手くいかず、2ページ目以降がNot Foundになることがあった。詳しい条件は不明。そこまで調べる気もないし。
その場合はWordPressの管理画面から設定→表示設定の中にある「1ページに表示する最大投稿数」をposts_per_pageに指定した値よりも小さくすればいい。
- カテゴリ別月別アーカイブページの作成
-
上記のプラグインを使うのが一番手っ取り早い。
以下、以前にメモっておいたプラグインを使わずにどうにかする方法。2.9とかで動作するのかどうかは知らない。結構めんどい。修正が必要な記述だけを抜き出してるから、そのままfunctions.phpにコピペしても動かないので注意。
カテゴリ別月別アーカイブリストの出力
「wp-includes」ディレクトリ内の「general-template.php」に記述されているwp_get_archives関数をカスタマイズする。基本的にテーマ内に「functions.php」を作成し、その中にカスタマイズした関数 ((コアファイルを直接弄るとバージョンアップしたときに面倒。))を記述する。関数名は仮に「wp_get_archives_custom」とする。
関数の引数である文字列にカテゴリID(term_id)である「mcat」を加える。
function wp_get_archives_custom($args = '') { global $wpdb, $wp_locale; $defaults = array( 'type' => 'monthly', 'limit' => '', 'format' => 'html', 'before' => '', 'after' => '', 'show_post_count' => false, 'mcat' => false //デフォルト値はなし );
月別アーカイブリストを処理している部分を書き換える
if ( 'monthly' == $type ) { if($mcat){ //$mcatが空でなければ $taxID = $wpdb->get_var("SELECT term_taxonomy_id FROM $wpdb->term_taxonomy WHERE $wpdb->term_taxonomy.term_id = $mcat",0,0);//※1 $query = "SELECT DISTINCT YEAR(post_date) AS year, MONTH(post_date) AS month, count(ID) as posts FROM $wpdb->posts, $wpdb->term_relationships WHERE $wpdb->posts.ID = $wpdb->term_relationships.object_id AND $wpdb->term_relationships.term_taxonomy_id = $taxID AND $wpdb->posts.post_type = 'post' AND $wpdb->posts.post_status = 'publish' GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date DESC" . $limit;//※2 } else { //$mcatが空であれば $query = "SELECT DISTINCT YEAR(post_date) AS `year`, MONTH(post_date) AS `month`, count(ID) as posts FROM $wpdb->posts $join $where GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date DESC $limit"; } $key = md5($query); $cache = wp_cache_get( 'wp_get_archives' , 'general'); if ( !isset( $cache[ $key ] ) ) { $arcresults = $wpdb->get_results($query); $cache[ $key ] = $arcresults; wp_cache_add( 'wp_get_archives', $cache, 'general' ); } else { $arcresults = $cache[ $key ]; } if ( $arcresults ) { $afterafter = $after; foreach ( $arcresults as $arcresult ) { $url = get_month_link($arcresult->year,$arcresult->month); $text = sprintf(__('%1$s %2$d'), $wp_locale->get_month($arcresult->month), $arcresult->year); if ( $show_post_count ) $after = ' ('.$arcresult->posts.')' . $afterafter; echo get_archives_link_custom($url, $text, $format, $before, $after, $mcat); //※3 } } }
- ※1
- 関数の引数として与える値はカテゴリID(term_id)である。しかし、実際に記事とカテゴリを結び付けている値は’term_taxonomy_id’であるため、’term_id’から’term_taxonomy_id’を取得する必要がある
- ※2
- ‘$mcat’に値が指定されていた場合のSQL文に変更を加える
- ※3
- アーカイブリンクのURLを取得する関数にも変更を加える必要があり、引数に’$mcat’を追加する。
- ※4
- これはあくまでもアーカイブのリストを取り出す方法なので、archive.php自体は別途記述しないとダメ。$mcatがURLパラメータに含まれていたらどうこうする、みたいな感じでquery_posts()あたりで条件指定する必要がある。
アーカイブリンクのURLを取得する関数にカテゴリ関係の処理を追加する
function get_archives_link_custom ($url, $text, $format = 'html', $before = '', $after = '', $mcat) { $text = wptexturize($text); $title_text = attribute_escape($text); $url = clean_url($url); if($mcat) { //$mcatが空でなければ $url = $url."?mcat=".$mcat; } if ('link' == $format) return "\t\n"; elseif ('option' == $format) return "\t\n"; elseif ('html' == $format) return "\t
- $before$text$after
\n"; else // custom return "\t$before$text$after\n"; }オリジナルの関数に、引数$mcatに値が指定されていた場合は出力するURLにGET変数として$mcatの値を加える処理を追加。
- カテゴリID(term_id)からカテゴリ名またはスラッグを取得
関数の引数は「カテゴリID」と「取得したい値の種類( ‘name’ または ‘slug’ )」
function get_category_name_by_id($cat_ID,$type) { $cat_ID = (int) $cat_ID; $category = &get_category($cat_ID); if($type == 'name'){ return $category->cat_name; } elseif($type == 'slug') { return $category->slug; } }
- 投稿呼び出しクエリの初期化
記事等の呼び出しループが終了したあと上のように記述するとquery_stringを初期化することができる。
wp_reset_query()を使った方が簡単確実。
Document Info.
- Published
- 11:12 on Saturday, Jul 12, 2008
- Last Modified
- 1:10 on Thursday, Nov 29, 2012
- Writer
- Rusica