<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2japanesefull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:xhtml="http://www.w3.org/1999/xhtml" version="2.0">

<channel>
	<title>wpxtreme</title>
	
	<link>http://wpxtreme.jp</link>
	<description>XTREME WORDPRESS STUNTS</description>
	<lastBuildDate>Fri, 16 Dec 2011 04:26:02 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://wpxtreme.jp/feed" />
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/Wpxtreme" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="wpxtreme" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://paipo.jp/bookmarklet/?url=http%3A%2F%2Ffeeds.feedburner.com%2FWpxtreme" src="http://www.feedburner.jp/fb/i/subscribe_paipo.gif">Paipo???</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://add.my.yahoo.co.jp/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2FWpxtreme" src="http://i.yimg.jp/i/jp/my/addtomy/standard_bb.gif">myyahoo???</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2FWpxtreme" src="http://www.newsgator.com/images/ngsub1.gif">NewsGator Online???</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://feedpath.jp/feedreader/feeds_add?url=http%3A%2F%2Ffeeds.feedburner.com%2FWpxtreme" src="http://feedpath.jp/common/images/sub_feedpath.gif">feedpath???</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.bloglines.com/sub/http://feeds.feedburner.com/Wpxtreme" src="http://www.bloglines.com/images/sub_modern11.gif">Bloglines???</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2FWpxtreme" src="http://buttons.googlesyndication.com/fusion/add.gif">Google???</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://r.hatena.ne.jp/append/http://feeds.feedburner.com/Wpxtreme" src="http://r.hatena.ne.jp/images/addto_w.gif">???RSS???</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://reader.livedoor.com/subscribe/http://feeds.feedburner.com/Wpxtreme" src="http://image.reader.livedoor.com/img/banner/91_17_1.gif">Livedoor???????</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://reader.goo.ne.jp/web/bookmarklet.html?,,http%3A%2F%2Ffeeds.feedburner.com%2FWpxtreme" src="http://reader.goo.ne.jp/web/img/addwebrss.gif">goo RSS???????</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.live.com/?add=http%3A%2F%2Ffeeds.feedburner.com%2FWpxtreme" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://mix.excite.eu/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2FWpxtreme" src="http://image.excite.co.uk/mix/addtomix.gif">Subscribe with Excite MIX</feedburner:feedFlare><item>
		<title>WordPress で「全◯件中◯件〜◯件目を表示」を表示する</title>
		<link>http://wpxtreme.jp/display-search-or-archive-count-in-wordpress</link>
		<comments>http://wpxtreme.jp/display-search-or-archive-count-in-wordpress#comments</comments>
		<pubDate>Fri, 16 Dec 2011 03:40:15 +0000</pubDate>
		<dc:creator>kz</dc:creator>
				<category><![CDATA[TIPS]]></category>
		<category><![CDATA[archive]]></category>
		<category><![CDATA[category]]></category>
		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false">http://wpxtreme.jp/?p=975</guid>
		<description><![CDATA[検索結果や各種アーカイブなどの記事一覧でページネーションする場合によくある表示「全◯件中◯件〜◯件目を表示しています」の決定版をお届けします。件数取得のために改めて get_posts() 的なことをしないので WordPress に優しい作りです。また posts_per_page = -1 のときに $wp_query->found_posts が 0 になる不具合にも対応済です。<br />ただし、不正なページ指定による Not Found 時やハナから have_posts() が false な場合に何らかの表示が必要な場合は、別途対応してください。
<a class="excerpt-more" href="http://wpxtreme.jp/display-search-or-archive-count-in-wordpress">Continue Reading &#187;</a>]]></description>
			<content:encoded><![CDATA[<h4>ちょっと長いですが</h4>
<p>テーマフォルダの functions.php に以下を追加します。</p>
<pre class="code"><code>function my_result_count() {
  global $wp_query;

  $paged = get_query_var( &#039;paged&#039; ) - 1;
  $ppp   = get_query_var( &#039;posts_per_page&#039; );
  $count = $total = $wp_query-&gt;post_count;
  $from  = 0;
  if ( 0 &lt; $ppp ) {
    $total = $wp_query-&gt;found_posts;
    if ( 0 &lt; $paged )
      $from  = $paged * $ppp;
  }
  printf(
    &#039;&lt;p&gt;全%1$s件中 %2$s%3$s件目を表示&lt;/p&gt;&#039;,
    $total,
    ( 1 &lt; $count ? ($from + 1 . &#039;〜&#039;) : &#039;&#039; ),
    ($from + $count )
  );
}</code></pre>



<h4>使い方</h4>
<p>index.php, archive.php, category.php, date.php などの記事一覧系テンプレートファイルに、以下のように書きます。</p>
<pre class="code"><code>if ( have_posts() ) : 
  my_result_count();  // ここら辺で表示します
  while ( have_posts() ) :
    the_post();
    /* do stuff */
  endwhile;
else :
  /* Nothing Found */
endif;
</code></pre>



<h4>ちなみに</h4>
<p>「全部で◯件」を取得するだけなら以下のように書けば OK ◎</p>
<pre class="code"><code>$count = 0 &lt; get_query_var( &#039;posts_per_page&#039; ) ? $wp_query-&gt;found_posts : $wp_query-&gt;post_count;</code></pre>


<p>※ functions.php など、テンプレートファイル以外に書く場合は予め <code>global $wp_query;</code> の記述も必要です。</p>
]]></content:encoded>
			<wfw:commentRss>http://wpxtreme.jp/display-search-or-archive-count-in-wordpress/feed</wfw:commentRss>
		<slash:comments>24</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://wpxtreme.jp/display-search-or-archive-count-in-wordpress" />
	</item>
		<item>
		<title>WordPress ループ＆クエリーのモヤモヤを解消しよう！</title>
		<link>http://wpxtreme.jp/understanding-wordpress-loops-and-queries</link>
		<comments>http://wpxtreme.jp/understanding-wordpress-loops-and-queries#comments</comments>
		<pubDate>Mon, 12 Dec 2011 03:40:40 +0000</pubDate>
		<dc:creator>kz</dc:creator>
				<category><![CDATA[TUTORIALS]]></category>
		<category><![CDATA[action]]></category>
		<category><![CDATA[modifications]]></category>
		<category><![CDATA[query]]></category>

		<guid isPermaLink="false">http://wpxtreme.jp/?p=913</guid>
		<description><![CDATA[12月25日まで毎日ブログをつないでいく <a href="http://atnd.org/events/22823">WordPress Advent Calendar</a>、12日目担当 福山カズヒデ (<a href="http://twitter.com/#!/kzxtreme">@kzxtreme</a>) です、こんにちは。aka aus Cothodyntomo（<a href="http://twitter.com/#!/aka_aus_pd">@aka_aus_pd</a>）さんの「<a href="http://plasticdreams.org/archives/2011/12/11/2830/rusty-nails/">錆びたブログをまた動かすときに必要な事柄</a>」からバトンをいただきました！<br />WordPress 都市伝説のひとつ「query_posts() は危険」のデマは、地道な「wp_reset_query() を使おうキャンペーン」によりかなり沈静化しましたが、それでもなお「get_posts() 以外は信用ならん」「WP_Query 最強！」と各派閥がシノギを削る争いを繰り広げています。ラブ＆ピースなクリスマスを迎えるために、WordPress の最も基本的な機能でありながら最も正しく理解されていないこの最大のモヤモヤを、今日ここでスッキリと解消してしまいましょう！<a class="excerpt-more" href="http://wpxtreme.jp/understanding-wordpress-loops-and-queries">Continue Reading &#187;</a>]]></description>
			<content:encoded><![CDATA[<h4>複数ループ</h4>
<p>index.php などで</p>
<pre class="code"><code>while( have_posts() ) : the_post();
    /* do stuff */
endwhile;</code></pre>


<p>のように WordPress ループ（メインループ）の処理をいきなり書けるのは、テンプレートファイルが実行される時点ですでに「サイトにアクセスされた URL からクエリ変数を抽出し、それらの条件に一致する記事オブジェクトを取得している」からです。</p>
<p>そして、例えばホーム（トップページ）やサイドバーなどで、メインループとは別の条件で記事を取得（，出力）するループ処理がある場合、それらを複数ループ（Multiple Loops）と言います。<br />
ここでよくある不具合が</p>
<ul>
  <li>サイドバーやフッターで条件分岐タグが正しく判定されない。</li>
  <li>ページネーションが正しくできない。</li>
  <li>$post を使う関数の結果が正しくない。</li>
</ul>
<p>などなど。。。エラーにならないけど値が変わっている、動作がおかしい、WordPress は不安定？と、謎現象として長らく恐れられています。</p>

<h4>グローバル変数の扱いを理解しよう</h4>

<p>複数ループは不安定、危険などと言われる原因は、ループ＆クエリーでのグローバル変数の扱いが十分に理解されていないことにあります。</p>
<p>以下は、ループ＆クエリーに関係のある主なグローバル変数です。</p>
<pre class="code"><code>$wp_the_query ..... WP_Query オブジェクト。URL のクエリーバックアップ用。
$wp_query ......... WP_Query オブジェクト。カレントのクエリー。
$posts ............ クエリーを実行して取得した記事オブジェクトの配列。
$post ............. カレントの記事オブジェクト。</code></pre>



<p>そして、これらのグローバル変数を上書きする関数は以下の通り。</p>
<pre class="code"><code>query_posts() ........................ $wp_query を上書き。
the_post(), WP_Query::the_post() ..... $post を上書き。
</code></pre>


<p>テンプレートファイル内では <code>$wp_query, $posts, $post</code> はグローバル変数として宣言されているので、これらも何らかの値を代入すれば上書きされます。
<p>さらに、上書きされたグローバル変数を復元する関数があります。</p>
<pre class="code"><code>wp_reset_query() ........ $wp_query を $wp_the_query, $post を $wp_query-&gt;post で復元。
wp_reset_postdata() ..... $post を $wp_query-&gt;post で復元。
</code></pre>


<p>例えば <code>is_category()</code> などの条件分岐タグや <code>posts_nav_link()</code> などはグローバル変数の <code>$wp_query</code> を元にしています。「メインループの状態が欲しいのにグローバル変数を上書きしたまま復元していない」「グローバル変数を復元した後に複数ループ側の状態を取得している」といった現在のグローバル変数の状態を正しく認識していないことが、複数ループにまつわる問題の原因です。</p>

<h4>正しい書き方</h4>
<p>以下は、<code>query_posts(), get_posts(), WP_Query()</code> 各々についての、現在のところ副作用が無く不具合を作り込み難い書き方です。なお、いずれの関数／クラスも内部では最終的に <code>WP_Query::get_posts()</code> を実行しています。
<h5>query_posts()</h5>
<pre class="code"><code>$arg = array( 
    /* 省略 */ 
    &#039;paged&#039; =&gt; get_query_var( &#039;paged&#039; ); // ページネーションするなら必須
);
query_posts( $args );
    while ( have_posts() ) : 
        the_post();
        /* do stuff 
           the_title(), the_permalink() 等使用可
        */
    endwhile;
    /* 必要なら endwhile 〜 wp_reset_query() の間でページネーション */
wp_reset_query();</code></pre>


<p>グローバル変数の <code>$wp_query, $post</code> を使うテンプレートタグ／関数がそのまま利用できるので便利です。ちなみに</p>
<pre class="code"><code>query_posts();
  /* */
query_posts();
  /* */
wp_reset_query();</code></pre>


<p>のように複数の <code>query_posts()</code> の最後に <code>wp_reset_query()</code> しても問題ありませんが、気持ち悪いのでやめましょう。</p>
<h5>get_posts()</h5>
<pre class="code"><code>$arg = array( 
    /* 省略 */ 
);
$my_posts = get_posts( $args );  //  $posts = とは書かない
    global $post;  // テンプレートファイル内なら書かなくても良い
    foreach ( $my_posts as $post ) : 
        setup_postdata( $post );
        /* do stuff 
           the_title(), the_permalink() 等使用可
        */
    endforeach;
wp_reset_postdata();</code></pre>


<p><code>$posts =</code> と書かないのは、<code>$posts</code> を復元する関数が用意されていないからです。他で使用されるフシが無く、</p>
<pre class="code"><code>$GLOBALS[&#039;posts&#039;] = &amp; $wp_query-&gt;posts;</code></pre>


<p>で復元すれば良さそうですが、余計なことはしない方が得策です。また、グローバル変数の <code>$post</code> を使用せず <code>$my_post</code> のようにも書けますが、<code>the_title()</code> などのテンプレートタグはグローバル <code>$post</code> 専用のため、<code>echo get_the_title( $my_post )</code> のように書く必要があります。
<p>ついでに <code>get_posts(), get_children()</code> は <code>query_posts(), WP_Query()</code>の WordPress ループの内側で入れ子ループとしても利用できます。そういえばメインループから見るとここで挙げている3つの関数／クラスはどれも二重ループの内側になりますね。</p>
<p>ただし <code>query_posts(), get_posts(), WP_Query()</code> の同じ関数／クラスでループを入れ子にするのはやめましょう。その必要はまずありませんし、労多くして得るもの少なしです。</p>

<h5>WP_Query()</h5>
<pre class="code"><code>$arg = array( 
    /* 省略 */ 
);
$my_query = new WP_Query( $args );
    while ( $my_query-&gt;have_posts() ) : 
        $my_query-&gt;the_post();  // global の $post を上書きする
        /* do stuff 
           the_title(), the_permalink() 等使用可
        */
    endwhile;
wp_reset_postdata();</code></pre>


<p><code>$my_query->the_post()</code> がグローバル変数の <code>$post</code> を上書きすることに注意しましょう。これよりは <code>query_posts()</code> の方が素直で使い易いかな、と思います。</p>

<h4>クエリーの改変</h4>
<p>もしメインループとは別のループ、ではなく、メインループそのものを変更したいだけなら <code>pre_get_posts</code> アクションを使うと良いでしょう。WordPress はメインループ用に URL からクエリ変数を抽出し、条件に一致する記事オブジェクトを取得していますが、これにも <code>WP_Query::get_posts()</code> が使用されています。</p>
<p><code>pre_get_posts</code> アクションは、<code>WP_Query::get_posts()</code> の内部でオリジナルのクエリーからクエリ変数や条件分岐タグ用の変数を設定した後かつ記事オブジェクトを取得する前に実行されるため、元のクエリーを判定して新たなクエリーを与えることができます。複数ループにする必要がなくメインループだけで完結するので、クエリ実行のコストが節約できますね。</p>
<h5>例）カテゴリーアーカイブは1ページ20件で日付の昇順にする場合</h5>
<p>テーマフォルダの functions.php に以下を追加します。</p>
<pre class="code"><code>add_action( &#039;pre_get_posts&#039;, &#039;my_pre_get_posts&#039; );
function my_pre_get_posts( $query ) {
    if ( ! is_admin() &amp;&amp; is_category() ) {
        $query-&gt;set( &#039;posts_per_page&#039;, 20 );
        $query-&gt;set( &#039;order&#039;, &#039;ASC&#039; );
    }
}</code></pre>


<p><code>! is_admin()</code> の条件が無いと、管理画面でも有効になります。</p>


<h4>CONCLUSION</h4>
<p>謎めいた現象に見えても、プログラムは書いた通りにしか動いていないのでした。仕組みがわかりさえすればとてもシンプルなことでしたね。</p>
<p>明日は <a href="http://twitter.com/#!/shinichiN">@shinichiN</a> さんです！お楽しみに！</p><h5>動作確認バージョン</h5><ul class="tested-vers"><li>WordPress 3.2.1</li></ul>]]></content:encoded>
			<wfw:commentRss>http://wpxtreme.jp/understanding-wordpress-loops-and-queries/feed</wfw:commentRss>
		<slash:comments>51</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://wpxtreme.jp/understanding-wordpress-loops-and-queries" />
	</item>
		<item>
		<title>センスと理詰め</title>
		<link>http://wpxtreme.jp/sense-and-theory</link>
		<comments>http://wpxtreme.jp/sense-and-theory#comments</comments>
		<pubDate>Thu, 01 Dec 2011 04:27:33 +0000</pubDate>
		<dc:creator>kz</dc:creator>
				<category><![CDATA[TEXT]]></category>

		<guid isPermaLink="false">http://wpxtreme.jp/?p=885</guid>
		<description><![CDATA[<a href="http://takashi178.me/2011/11/web%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%81%AB%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%82%BB%E3%83%B3%E3%82%B9%E3%81%AF%E5%BF%85%E8%A6%81%E3%81%8B%EF%BC%9F/">Webデザインに”デザインセンス”は必要か？</a> という記事が興味深かったので、全然違う話になりますが Web デザインに限らず自分が思うことをまとめておきます。<a class="excerpt-more" href="http://wpxtreme.jp/sense-and-theory">Continue Reading &#187;</a>]]></description>
			<content:encoded><![CDATA[<h4>センスと理論</h4>
<p>昔カリスマ美容師が流行ったときにテレビで見た、クマさんみたいなチャラくない美容師さんとモデルさんのやりとりにこんなクダリがありました。</p>
<div class="talk">
<p>モデルさん「あのさ、ここ来るといっつもこっちだけ何故か長くされるんだけどどうして？」<br />
クマさん　「あ、ホントだ。なんでだろ、でもそうじゃないとキマらなくない？」<br />
モデルさん「そうなのよねー。他の人だとこうはならないのよね、すごいなぁ。」</p>
</div>
<p>みたいな。</p>
<p>クマさんは学校で学び習得した理論から、この女優の頭の形や髪の生え方・クセを計算して、髪の長さやカットの仕方を導き出しているわけではないんですね多分。もちろんそういうような理論はある気がしますが、それにハマっていないから彼にしかできないわけで、そらもうただ「なんとなく」なんていう理由なわけです。<br />
<p>ただしその「なんとなく」には理由があって、自分が一番シックリくることなんだと思います。それがその人のセンスであり、自分の脳内に快感物質が分泌されまくる方向です。多くの人がそのアウトプットをいいね！と感じるならセンスが良いということになるのでしょう。</p>
<p>このクマさんのカットの仕方を解析してみると、実に美しく理論的にまとめられるに違いありません。そして、その理論を習得した人はクマさんと同じようなカットができることでしょう。できない場合は、それは器用さとかスキルの限界なのかもしれません、ごめんなさい。</p>
<h4>インプットを増やそう</h4>
<p>ステキな曲を作り人々を感動させるアノ人だって、もしかしたら楽譜を読めないかもしれない。YOUNG GUITAR の表紙を飾る彼なんて、もしかしたらタブ譜しか読めないかもしれない。でも理論を学べば、表現が広がり生み出す力がもっと豊かになるでしょう。例えベタにも程がありますが、自分の力だけで何もかもを生み出すことはできません。より良いより多くのアウトプットができるように、多くを学びたいですね。</p>
<p>もちろん、理論として完成されたものを学ぶだけでなく、普段から良いものに触れておくことも大切だと思います。元ネタのブログにある「様々なWebデザインを見て引き出しを増やしておく」ことがそれですね。誰かが体系的にまとめていなくても、私達の脳はインプットすればするほど、それらをゴニョゴニョして自分の創造力にしてくれます。そしてその創造力やアウトプットの「程度」が「センス」なのかな、と思います。</p>
<h4>分解能を上げよう</h4>
<p>例えば、この画像：</p>
<p><img src="http://wpxtreme.jp/cms/wp-content/uploads/2011/12/logos.jpg" alt="" title="logos" width="556" height="100" class="alignnone size-full wp-image-889" /></p>
<p>大差はないかもしれませんが、右側は色々やりすぎに感じます。いやぁ、そんなん好みちゃうのん？って話かもしれませんが、ここで言いたいのは「この左右の違いを認識していて自分で描くときにどの程度が最適かを繊細に調整できるかどうか」ということです。「文字の上側にドロップシャドウを入れて型押しの効果を出す」ときに右の画像しか出てこないと、まだまだインプットが足りないかもしれません。</p>
<p>そしてインプットは漫然と「すげーなー」とか「ステキだなー」と眺めるだけではなくて、サイズや濃淡、距離など何故良いと感じるのかを細かく認識するようにすると良いでしょう。この認識の分解能の高さを上げることが、自分のセンスを鍛え、結果としてアウトプットのクオリティの高さにつながるような気がします。<br />
この画像の差が「Web サイトの効果」にどれだけ影響するかは謎ですが、Web デザイナーと名乗るなら意識しておくと何かと良いかもしれませんね。</p>
]]></content:encoded>
			<wfw:commentRss>http://wpxtreme.jp/sense-and-theory/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://wpxtreme.jp/sense-and-theory" />
	</item>
		<item>
		<title>WordPress のURLクエリストリングにカスタムフィールドを指定して絞り込み検索する</title>
		<link>http://wpxtreme.jp/search-with-custom-fields-in-url-query-parameters</link>
		<comments>http://wpxtreme.jp/search-with-custom-fields-in-url-query-parameters#comments</comments>
		<pubDate>Wed, 30 Nov 2011 04:48:42 +0000</pubDate>
		<dc:creator>kz</dc:creator>
				<category><![CDATA[TIPS]]></category>
		<category><![CDATA[modifications]]></category>
		<category><![CDATA[query]]></category>

		<guid isPermaLink="false">http://wpxtreme.jp/?p=876</guid>
		<description><![CDATA[例として、スタッフ紹介ページに［部署］［性別］のカスタムフィールドがある場合、で話をしますね。<br />
<ul>
  <li>投稿タイプ：staff</li>
  <li>カスタムフィールド：division, gender</li>
</ul>
な感じの記事にカスタムフィールドの条件をつけて検索してみましょう。<a class="excerpt-more" href="http://wpxtreme.jp/search-with-custom-fields-in-url-query-parameters">Continue Reading &#187;</a>]]></description>
			<content:encoded><![CDATA[<h4>PHP での絞り込みなら</h4>
<p>詳しくは <a href="http://codex.wordpress.org/Class_Reference/WP_Query#Custom_Field_Parameters">Codex</a> を参照してくださいですが、<code>query_posts()</code> や <code>get_posts()</code> など、PHP コードでなら以下のように書けますね。</p>
<pre class="code"><code>query_posts( array(
    &#039;post_type&#039;  =&gt; &#039;staff&#039;,
    &#039;meta_key&#039;   =&gt; &#039;division&#039;,
    &#039;meta_value&#039; =&gt; &#039;sales&#039;,
    /* 他のパラメータは省略 */
) );</code></pre>


<p>メタクエリーを使えば、複数の条件を組み合わせることができます。</p>
<pre class="code"><code>query_posts( array(
    &#039;meta_query&#039; =&gt; array(
        array(
            &#039;key&#039;     =&gt; &#039;division&#039;,
            &#039;value&#039;   =&gt; &#039;sales&#039;,
        ),
        array(
            &#039;key&#039;     =&gt; &#039;gender&#039;,
            &#039;value&#039;   =&gt; &#039;male&#039;,
        ),
    ),
    /* 他のパラメータは省略 */
) );</code></pre>



<h4>簡単な方法</h4>
<p>同様に URL にクエリパラメータを付ければできそうな気がしますが、</p>
<pre class="code"><code>http://example.com/staff/?meta_key=division&amp;meta_value=sales</code></pre>


これは無視されます。URL に使用できるクエリ変数は <code>wp-includes/class-wp.php</code> の始めの方で <code>$public_query_vars</code> に指定されています。で、 これには <code>meta_key, meta_value</code> がありません。</p>
<p>ないなら、付け足せばいいじゃない的な解決方法が以下です。テーマフォルダの functions.php に書けば OK。</p>
<pre class="code"><code>add_filter( &#039;query_vars&#039;, &#039;my_query_vars&#039; );
function my_query_vars( $public_query_vars ) {
    return array_merge( $public_query_vars, array( &#039;meta_key&#039;, &#039;meta_value&#039; ) );
}</code></pre>


<p>これで、先ほどの <code>?meta_key=division&#038;meta_value=sales</code> が有効になります。ただし、複数の条件を指定することはできません。</p>

<h4>よりクールな方法</h4>
<p>いやでも URL に <code>meta_key</code> とか <code>meta_value</code> とかダサくないだろうか。えびちゃんドン引きしちゃうんじゃないだろうか。こんなことならカスタムフィールドじゃなくてカスタム分類（タクソノミー）で作っておけばよかった。カスタム分類なら、</p>
<pre class="code"><code>http://example.com/staff/?division=sales</code></pre>


<p>ってスマートに書けるのに。カスタム分類は敷居が高いからずっと避けていた。納期もアレだから安直にカスタムフィールドで済ませてしまっていた。いつまでもそうやって逃げてるの？そう言われて何も言い返せなかった。オレ、このままでいいんだろうか。。。</p>
<p>&nbsp;</p>
<p>と、お悩みのアナタに以下のコードを捧げます。テーマの functions.php に書きましょう◎</p>
<pre class="code"><code>global $my_public_query_vars;
$my_public_query_vars = array( &#039;division&#039;, &#039;gender&#039; );

add_filter( &#039;query_vars&#039;, &#039;my_query_vars&#039; );
function my_query_vars( $public_query_vars ) {
    global $my_public_query_vars;
    return array_merge( $public_query_vars, $my_public_query_vars );
}

add_action( &#039;pre_get_posts&#039;, &#039;my_pre_get_posts&#039; );
function my_pre_get_posts( $query ) {
 &nbsp; &nbsp;if ( ! is_admin() &amp;&amp; is_post_type_archive( &#039;staff&#039; ) /* &amp;&amp; &#039;staff&#039; == $query-&gt;get( &#039;post_type&#039; ) */ ) {
 &nbsp; &nbsp; &nbsp; &nbsp;$meta_query = array();
 &nbsp; &nbsp; &nbsp; &nbsp;
        global $my_public_query_vars;
 &nbsp; &nbsp; &nbsp; &nbsp;foreach ( $my_public_query_vars as $key ) {
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if ( $val = $query-&gt;get( $key ) ) {
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$meta_query[] = array(
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#039;key&#039; &nbsp; =&gt; $key,
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&#039;value&#039; =&gt; $val,
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;);
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
 &nbsp; &nbsp; &nbsp; &nbsp;}
 &nbsp; &nbsp; &nbsp; &nbsp;
 &nbsp; &nbsp; &nbsp; &nbsp;if ( ! empty( $meta_query ) ) {
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$query-&gt;set( &#039;meta_query&#039;, $meta_query );
 &nbsp; &nbsp; &nbsp; &nbsp;}
 &nbsp; &nbsp;}
}</code></pre>


<p>もちろん、以下のような複数条件も指定できます。</p>
<pre class="code"><code>http://example.com/staff/?division=sales&amp;gender=male</code></pre>



<h4>おまけ：クエリ変数付きの URL を PHP で作る方法</h4>
<p>投稿タイプが staff で、部署が sales で性別が male な URL は</p>
<pre class="code"><code>add_query_arg( 
    array(
        &#039;division&#039; =&gt; &#039;sales&#039;,
        &#039;gender&#039;   =&gt; &#039;male&#039;,
    ),
    get_post_type_archive_link( &#039;staff&#039; )
);</code></pre>


<p>で作成できます。<code>add_query_arg()</code> って何やねん、と気になったコードジャンキーな方は <a href="http://phpxref.ftwr.co.uk/wordpress/nav.html?_functions/index.html">PHPXref 0.7: WordPress</a> でソース見てみてん◎</p>

<h4>CONCLUSION</h4>
<p>コンテンツ設計というかデータ設計というか、そういうものはしっかりキッチリ練っておきましょうね！</p><h5>動作確認バージョン</h5><ul class="tested-vers"><li>WordPress 3.2.1</li></ul>]]></content:encoded>
			<wfw:commentRss>http://wpxtreme.jp/search-with-custom-fields-in-url-query-parameters/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://wpxtreme.jp/search-with-custom-fields-in-url-query-parameters" />
	</item>
		<item>
		<title>WordPress でカテゴリーAの記事をフィード配信するときにカテゴリBに属していたら除く</title>
		<link>http://wpxtreme.jp/feed-posts-in-category-a-and-not-in-category</link>
		<comments>http://wpxtreme.jp/feed-posts-in-category-a-and-not-in-category#comments</comments>
		<pubDate>Tue, 29 Nov 2011 08:40:00 +0000</pubDate>
		<dc:creator>kz</dc:creator>
				<category><![CDATA[TIPS]]></category>
		<category><![CDATA[feed]]></category>
		<category><![CDATA[modifications]]></category>
		<category><![CDATA[query]]></category>

		<guid isPermaLink="false">http://wpxtreme.jp/?p=857</guid>
		<description><![CDATA[はい、できます！ 言い換えると カテゴリーID：1に属する記事を配信、かつ カテゴリーID：2に属する記事は配信しない となりますので（例ね）、我らがクエリ改変の切り札 pre_get_posts アクションを使って、そ ...]]></description>
			<content:encoded><![CDATA[<div class="excerpt"><!-- tweet id : 141406950574407680 --><style type='text/css'>#bbpBox_141406950574407680 a { text-decoration:none; color:#FF3300; }#bbpBox_141406950574407680 a:hover { text-decoration:underline; }</style><div id='bbpBox_141406950574407680' class='bbpBox' style='padding:20px; margin:5px 0; background-color:#709397; background-image:url(http://a1.twimg.com/images/themes/theme6/bg.gif); background-repeat:no-repeat'><div style='background:#fff; padding:10px; margin:0; min-height:48px; color:#333333; -moz-border-radius:5px; -webkit-border-radius:5px;'><span style='width:100%; font-size:18px; line-height:22px;'>WP&#12391;&#12459;&#12486;&#12468;&#12522;A&#12398;RSS&#12434;&#37197;&#20449;&#12377;&#12427;&#38555;&#12395;&#12289;&#12459;&#12486;&#12468;&#12522;A&#12392;B&#12395;&#30331;&#37682;&#12375;&#12390;&#12427;&#12456;&#12531;&#12488;&#12522;&#12399;&#30465;&#12365;&#12383;&#12356;&#12435;&#12384;&#12369;&#12393;&#12289;&#12381;&#12422;&#12371;&#12392;&#12391;&#12365;&#12427;&#12398;&#12363;&#12375;&#12425;&#12290;</span><div class='bbp-actions' style='font-size:12px; width:100%; padding:5px 0; margin:0 0 10px 0; border-bottom:1px solid #e6e6e6;'><img align='middle' src='http://wpxtreme.jp/cms/wp-content/plugins/twitter-blackbird-pie//images/bird.png' /><a title='tweeted on 2011.11.29 3:43 pm' href='http://twitter.com/#!/take_it02/status/141406950574407680' target='_blank'>2011.11.29 3:43 pm</a> via <a href="http://www.tweenapp.org/" rel="nofollow" target="blank">Tween</a><a href='https://twitter.com/intent/tweet?in_reply_to=141406950574407680' class='bbp-action bbp-reply-action' title='Reply'><span><em style='margin-left: 1em;'></em><strong>Reply</strong></span></a><a href='https://twitter.com/intent/retweet?tweet_id=141406950574407680' class='bbp-action bbp-retweet-action' title='Retweet'><span><em style='margin-left: 1em;'></em><strong>Retweet</strong></span></a><a href='https://twitter.com/intent/favorite?tweet_id=141406950574407680' class='bbp-action bbp-favorite-action' title='Favorite'><span><em style='margin-left: 1em;'></em><strong>Favorite</strong></span></a></div><div style='float:left; padding:0; margin:0'><a href='http://twitter.com/intent/user?screen_name=take_it02'><img style='width:48px; height:48px; padding-right:7px; border:none; background:none; margin:0' src='http://a2.twimg.com/profile_images/1636771557/wptake20111110_normal.png' /></a></div><div style='float:left; padding:0; margin:0'><a style='font-weight:bold' href='http://twitter.com/intent/user?screen_name=take_it02'>@take_it02</a><div style='margin:0; padding-top:2px'>&#12383;&#12369;</div></div><div style='clear:both'></div></div></div><!-- end of tweet --></div>
<h4>はい、できます！</h4>
<p>言い換えると</p>
<ul>
  <li>カテゴリーID：1に属する記事を配信、かつ</li>
  <li>カテゴリーID：2に属する記事は配信しない</li>
</ul>
<p>となりますので（例ね）、我らがクエリ改変の切り札 <code>pre_get_posts</code> アクションを使って、そのままの処理を テーマフォルダの functions.php に記述します。</p>
<pre class="code"><code>add_action( &#039;pre_get_posts&#039;, &#039;my_pre_get_posts&#039; );
function my_pre_get_posts( $query ) {
    if ( is_feed() ) {    // フィードだったら
        $query-&gt;set( &#039;category__in&#039;    , 1 );  // カテゴリーID：1を含める      
        $query-&gt;set( &#039;category__not_in&#039;, 2 );  // カテゴリーID：2は含めない
    }
}</code></pre>


<p>動作テストする時はフィードの内容が即時反映されるように、記事を追加したり削除したりして WordPress に「ぁ、記事集め直さなかん」って思わせるようにしてね（はぁと </p>
<p class="append">もちろん、含める／含めないカテゴリーは以下のように複数指定できます。</p>
<pre class="code"><code>add_action( &#039;pre_get_posts&#039;, &#039;my_pre_get_posts&#039; );
function my_pre_get_posts( $query ) {
    if ( is_feed() ) {    // フィードだったら
        $query-&gt;set( &#039;category__in&#039;    , array( 1, 2, 3 ) );  // カテゴリーID：1, 2, 3 を含める      
        $query-&gt;set( &#039;category__not_in&#039;, array( 4, 5, 6 ) );  // カテゴリーID：4, 5, 6 は含めない
    }
}</code></pre>


<h5>動作確認バージョン</h5><ul class="tested-vers"><li>WordPress 3.1.3</li></ul>]]></content:encoded>
			<wfw:commentRss>http://wpxtreme.jp/feed-posts-in-category-a-and-not-in-category/feed</wfw:commentRss>
		<slash:comments>17</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://wpxtreme.jp/feed-posts-in-category-a-and-not-in-category" />
	</item>
		<item>
		<title>WordPress でカスタムフィールドの日付から年別アーカイブリストを作成する</title>
		<link>http://wpxtreme.jp/yearly-archive-using-custom-field-in-wordpress</link>
		<comments>http://wpxtreme.jp/yearly-archive-using-custom-field-in-wordpress#comments</comments>
		<pubDate>Wed, 16 Nov 2011 05:33:28 +0000</pubDate>
		<dc:creator>kz</dc:creator>
				<category><![CDATA[TIPS]]></category>
		<category><![CDATA[action]]></category>
		<category><![CDATA[archive]]></category>
		<category><![CDATA[meta]]></category>
		<category><![CDATA[modifications]]></category>
		<category><![CDATA[query]]></category>

		<guid isPermaLink="false">http://wpxtreme.jp/?p=829</guid>
		<description><![CDATA[元ネタは WordPress 日本語公式フォーラムの「<a href="http://ja.forums.wordpress.org/topic/8389">カスタムフィールドの日付から年別アーカイブリストを作成</a>」です。このような、投稿の日付ではなくてカスタムフィールドに入力した日付でイベントカレンダー的なこととか、そらもう色んなことをひととおりしたい、というご要望は wpxtreme にもたくさん寄せられます。かなりの需要があると思われますので、自力で頑張りたい人のために一例としてやってみます。<a class="excerpt-more" href="http://wpxtreme.jp/yearly-archive-using-custom-field-in-wordpress">Continue Reading &#187;</a>]]></description>
			<content:encoded><![CDATA[<h4>仕様</h4>
<ul>
  <li>カスタムフィールドに入力した日付を元に、年別アーカイブ一覧を出力したり年別アーカイブを表示したりする。</li>
  <li>カスタムフィールドの値の書式は 'yyyy年mm月dd日'。</li>
  <li>カスタムフィールドのキーは 英数字。</li>
</ul>
<h4>使い方</h4>
<p><a href="http://wpdocs.sourceforge.jp/%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%82%BF%E3%82%B0/wp_get_archives">wp_get_archives()</a> とほぼ同じですが、パラメータがちょびっと違ってます。</p>
<h5>書式</h5>
<pre class="code"><code>&lt;?php 
my_get_year_archives( array(
	&#039;date_field&#039; =&gt; &#039;mydate&#039;,
) );
?&gt;</code></pre>


<h5>パラメータ</h5>
<ul>
  <li><strong>type</strong><br />このパラメータはありません。</li>
  <li><strong>datre_field</strong><br />（文字列）日付用のカスタムフィールドのキー。初期値は 'date'。</li>
</ul>
ちなみに <a href="http://wpdocs.sourceforge.jp/%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%82%BF%E3%82%B0/get_archives">get_archives()</a> は WordPress 2.1 でとっくに deprecated（非推奨）になってるので、<a href="http://wpdocs.sourceforge.jp/%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%82%BF%E3%82%B0/wp_get_archives">wp_get_archives()</a> を使うようにしましょう！
<h4>コード</h4>
<p>以下をテーマの functions.php にペッとすれば OK◎ タブが激しいですけど、気にしないで。</p>
<pre class="code"><code>&lt;?php
function my_get_year_archives( $args = &#039;&#039; ) {
	global $wpdb, $wp_locale;

	$defaults = array(
		&#039;date_field&#039; =&gt; &#039;date&#039;,
		&#039;format&#039; =&gt; &#039;html&#039;,
		&#039;echo&#039; =&gt; true,
		&#039;limit&#039; =&gt; &#039;&#039;,
		&#039;before&#039; =&gt; &#039;&#039;,
		&#039;after&#039; =&gt; &#039;&#039;, 
		&#039;show_post_count&#039; =&gt; false,
	);

	$r = wp_parse_args( $args, $defaults );
	extract( $r, EXTR_SKIP );

	if ( &#039;&#039; != $limit ) {
		$limit = absint( $limit );
		$limit = &#039; LIMIT &#039;.$limit;
	}

	$field  = &#039;m.meta_value&#039;;
	$select = &quot;SELECT SUBSTRING($field,1,4) AS `year`, count(p.ID) AS posts&quot;;
	$where  = &quot;WHERE p.post_type = &#039;post&#039; AND p.post_status = &#039;publish&#039;&quot;;
	$where .= $wpdb-&gt;prepare( &#039; AND m.meta_key = %s&#039;, $date_field );
	$join   = &quot; INNER JOIN $wpdb-&gt;postmeta AS m ON m.post_id = p.ID&quot;;
	
	$where  = apply_filters( &#039;getarchives_where&#039;, $where, $r );
	$join   = apply_filters( &#039;getarchives_join&#039; , $join , $r );

	$output = &#039;&#039;;
	$query = &quot;$select FROM $wpdb-&gt;posts AS p $join $where GROUP BY SUBSTRING($field,1,4) ORDER BY $field DESC $limit&quot;;
	$key = md5( $query );
	$cache = wp_cache_get( &#039;my_get_year_archives&#039; , &#039;general&#039; );
	if ( !isset( $cache[ $key ] ) ) {
		$arcresults = $wpdb-&gt;get_results( $query );
		$cache[ $key ] = $arcresults;
		wp_cache_set( &#039;my_get_year_archives&#039;, $cache, &#039;general&#039; );
	} else {
		$arcresults = $cache[ $key ];
	}

	if ( $arcresults ) {
		$afterafter = $after;
		foreach ( (array) $arcresults as $arcresult ) {
			$url = add_query_arg( array( &#039;meta_key&#039; =&gt; $date_field ), get_year_link( $arcresult-&gt;year ) );
			$text = sprintf( &#039;%d&#039;, $arcresult-&gt;year );
			if ($show_post_count)
				$after = &#039;&amp;nbsp;(&#039;.$arcresult-&gt;posts.&#039;)&#039; . $afterafter;
			$output .= get_archives_link( $url, $text, $format, $before, $after );
		}
	}
		
	if ( $echo )
		echo $output;
	else
		return $output;
}

add_action( &#039;init&#039;, &#039;my_init&#039; );
function my_init() {
	global $wp;
	$wp-&gt;add_query_var( &#039;meta_key&#039; );
}

add_action( &#039;pre_get_posts&#039;, &#039;my_pre_get_posts&#039; );
function my_pre_get_posts( $query ) {
	if ( $query-&gt;is_year ) {
		$meta_query = array(
			array( 
				&#039;key&#039;     =&gt; $query-&gt;get( &#039;meta_key&#039; ),
				&#039;value&#039;   =&gt; $query-&gt;get( &#039;year&#039;     ),
				&#039;compare&#039; =&gt; &#039;LIKE&#039;
			),
		);
				
		$query-&gt;set( &#039;meta_query&#039; , $meta_query );
		$query-&gt;set( &#039;year&#039;       , &#039;&#039;          );
		$query-&gt;set( &#039;date&#039;       , &#039;&#039;          );
		$query-&gt;set( &#039;meta_key&#039;   , &#039;&#039;          );
	}
} 
?&gt;</code></pre>


<h4>ポイント</h4>
<p><strong>my_get_year_archives()</strong></p>
<ul>
  <li>指定されたカスタムフィールドの始めの4文字を「年」として、その年に記事が何件あるかを取得します。</li>
  <li>年アーカイブのリンクに日付用のカスタムフィールドのキーをクエリ変数としてくっつけます。</li>
</ul>
<p><strong>my_init()</strong></p>
<ul>
  <li>パブリックなクエリ変数に <code>meta_key</code> を追加します。<br />これをしとくと URL の後ろに '?meta_key=なんちゃら' の書式でお好みのクエリ変数が使えるようになります。パブリックなクエリ変数には元々どんなものがあるかは wp-includes/class-wp.php の始めの方にある <code>$public_query_vars</code> を見るといいですよ。</li>
</ul>
<p><strong>my_pre_get_posts()</strong><br />※WordPress は URL を元にどういう風に記事を取得するか判断します。<code>pre_get_posts</code> アクションではこの「どういう風に」の部分をコッソリ改変することができます。</p>
<ul>
  <li>年別アーカイブなら、<code>meta_key</code> で指定されたカスタムフィールドの値で該当する記事が取得されるように <code>meta_query</code> を仕込みます。</li>
</ul>
<h4>CONCLUSION</h4>
<p>フォーラムのご質問の仕様ビッチビチに作ってますので「私のやりたいことと微妙に違うの。」というえびちゃんは、このエントリーを参考に自分で何とかしてみてください。</p>
<p>でも、もしあなたが何日も解決できなくて泣きそうになったり、そんなんハナから自分でやるツモリのないえびちゃんだったりしたときは、wpxtreme までお気軽に <a href="http://wpxtreme.jp/contact">お問い合わせ</a> ください。</p>
<p>wpxtreme では、カスタマイズ1案件につき基本 10,500円（税込）にて承っております。数時間後〜どんなに重いカスタマイズでも翌日には納品いたしますよ。これまでたくさんの方々にお喜びいただいております。</p>
<p>さぁ！次はあなたの番です。きっと、圧倒的なスピードとクオリティで異次元のコストパフォーマンスを体験していただけることでしょう。</p>
<p>以上、あからさまな PR でした。</p><h5>動作確認バージョン</h5><ul class="tested-vers"><li>WordPress 3.1.3</li></ul>]]></content:encoded>
			<wfw:commentRss>http://wpxtreme.jp/yearly-archive-using-custom-field-in-wordpress/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://wpxtreme.jp/yearly-archive-using-custom-field-in-wordpress" />
	</item>
		<item>
		<title>Versions のライセンス登録時に “Connection error.  Please try again later.” となる場合の解決方法</title>
		<link>http://wpxtreme.jp/versions-how-to-solve-the-registration-probrem</link>
		<comments>http://wpxtreme.jp/versions-how-to-solve-the-registration-probrem#comments</comments>
		<pubDate>Mon, 31 Oct 2011 12:30:40 +0000</pubDate>
		<dc:creator>kz</dc:creator>
				<category><![CDATA[TROUBLESHOOTING]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Subversion]]></category>
		<category><![CDATA[Versions]]></category>

		<guid isPermaLink="false">http://wpxtreme.jp/?p=737</guid>
		<description><![CDATA[Mac 用のGUIベース Subversion クライアントといえば <a href="http://www.versionsapp.com/">Versions</a>, <a href="http://www.zennaware.com/cornerstone/">Cornerstone</a> が2強ですが、Web デザイナー的にはサイトデザインも各所で紹介されていた Versions の方に惹かれます。<br />
で、お試しで使っていた Versions デモ版が先日期限切れになったのでライセンスを購入しました。が、登録しようとすると "Connection error" とか言いやがって全然使えない。<br />
WordPress の簡単インストールに飼い慣らされた身にはキツイなコレ。こんなツライ思いをするのはもうボクで最後にしたい。というわけで、ググれどググれど解決方法が見当たらなかった腹いせにボクの辿った軌跡をココにシルしておきます。<a class="excerpt-more" href="http://wpxtreme.jp/versions-how-to-solve-the-registration-probrem">Continue Reading &#187;</a>]]></description>
			<content:encoded><![CDATA[<h4>ライセンス買ったのに登録できない</h4>
<p>んもぅ！何度も何度も出てきやがってこいつめ！今ちょっと混んでるけどしばらくすれば登録できるから！感出しやがってからに！登録できる気配がまるでないので、もしかしてこういう詐欺商法かな、と思ってしまいました。<br />
<a href="http://wpxtreme.jp/cms/wp-content/uploads/2011/10/11103107.jpg"><img src="http://wpxtreme.jp/cms/wp-content/uploads/2011/10/11103107.jpg" alt="Versions: Connection error. Please try again later" title="11103107" width="336" height="259" class="alignnone size-full wp-image-812" /></a>今回気づいたんですけど、Mac の場合、インストールとかがスンナリいかないと当該のアプリケーションに ウラアァァァァァアア！と呪いをかけてます。でも、Windows を使ってた頃は OS にオマエのせいじゃアァァッァア！と呪いをかけてましたね。。。</p>
<h4>ググる</h4>
<p>なんか問題があった場合は、まずググりましょう！ググれカス！ってどっかのオッサンも言ってましたし！Versions には <a href="http://groups.google.com/group/versions">Google グループ</a> があるのでソコが検索でひっかかります。言い換えると他には情報がありません。で、ソコでさらに検索すると<a href="http://groups.google.com/group/versions/search?group=versions&#038;q=register&#038;qt_g=%E3%81%93%E3%81%AE%E3%82%B0%E3%83%AB%E3%83%BC%E3%83%97%E3%82%92%E6%A4%9C%E7%B4%A2">ひどい状況</a> を目の当たりにできます。おぉぉ、もしかしてオレ $39 捨ててしもたんか。。。残念ながら、ググっても解決できませんでした。カスって言う人がカスなんだとボクは思います。</p>
<p><a href="http://twitter.com/#!/versionsapp">@versionapp</a> でも登録できない件についてちょいちょい問い合わせられてますね。毎度「とりあえずメールして！」って返信してはるけど解決してるんやろか。</p>
<h4>サポートに問い合わせる</h4>
<p>てか購入した製品で問題があったなら、まずサポートに問い合わせればいいじゃない！なんで知恵袋で訊いたりするわけ？知恵袋ってアレよね、なんか SNS 的使い方されてるのね。公開 DM みたいなんとか。ほぇーって感じ。恋愛カテとか業者の自演か全力中高生ばかりでとても癒されるし。ほぇー。<br />
それはともかく「サポートのレスポンス悪いんじゃ！」みたいなのをさっきいっぱい目にした気がしますが <a href="http://www.versionsapp.com/support">Versions サポートページ</a> の［Email］でイヤミちっくに［Inquiry Type］を "Bug Report" にしたら「登録できんよー」の旨を伝えましょう。</p>
<p>で、帰ってきたお返事をまとめると：</p>
<ul>
  <li>ファイアウォール、プロキシ、Little Snitch の類いをツコてたらそらアカンで！</li>
  <li>もしかすると SSL証明書かもわからんね</li>
</ul>
<p>だそうです。［システム環境設定｜セキュリティ｜FileVault］が「入」になっててもアカンらしいですよ。ウチの場合はファイアウォールとかの問題ではないので、 SSL証明書をやっつけてみます。</p>
<h4>証明書を受け入れさせる</h4>
<p>サポートからのお返事によれば「認証局のルート証明書をキーチェーンに追加して信頼設定するといいよ！」とのことですのでメンドくさいですがやってみましょう。</p>
<ol>
  <li><a href="https://register.madebysofa.com/versions/buy">https://register.madebysofa.com/versions/buy</a> にアクセス！<br />（以下 Safari でご説明します）</li>
  <li>証明書が怪しい旨をお知らせされますので［証明書を表示］ボタンをクリック後、証明書アイコンをデスクトップにドラッグ＆ドロップして証明書ファイルをゲットしましょう。<br /><a href="http://wpxtreme.jp/cms/wp-content/uploads/2011/10/11103101.jpg"><img src="http://wpxtreme.jp/cms/wp-content/uploads/2011/10/11103101-620x378.jpg" alt="" title="11103101" width="620" height="378" class="alignnone size-large wp-image-777" /></a></li>
  <li>そのファイル "register.madebysofa.com.cer" をダブルクリックすると「証明書の追加」ダイアログが表示されます。［キーチェーン］を「システムルート」にして（「ログイン」のママでも良いよ）［OK］ボタンをクリックします。<br />
<a href="http://wpxtreme.jp/cms/wp-content/uploads/2011/10/11103102.jpg"><img src="http://wpxtreme.jp/cms/wp-content/uploads/2011/10/11103102-620x308.jpg" alt="" title="11103102" width="620" height="308" class="alignnone size-large wp-image-758" /></a></li>
  <li>パスワードを求められる場合は、素直に応じます。今はまだ、そのときではありませんから。これでキーチェーンに追加されましたが、まだ信頼はされていません。これはきっと日頃の行いのせいでしょうね。。。<br /><a href="http://wpxtreme.jp/cms/wp-content/uploads/2011/10/11103103.jpg"><img src="http://wpxtreme.jp/cms/wp-content/uploads/2011/10/11103103-620x297.jpg" alt="" title="11103103" width="620" height="297" class="alignnone size-large wp-image-761" /></a></li>
  <li>証明書を選択して［キーチェーンアクセス｜ファイル｜情報を見る］をクリックします。表示されたダイアログの［信頼］をクリックして［この証明書を使用するとき：］を「常に信頼する」にします。これこそが本当の愛です。<br />
<a href="http://wpxtreme.jp/cms/wp-content/uploads/2011/10/11103104.jpg"><img src="http://wpxtreme.jp/cms/wp-content/uploads/2011/10/11103104-620x431.jpg" alt="" title="11103104" width="620" height="431" class="alignnone size-large wp-image-779" /></a>
※モザイクでヒミツっぽくしてみました。</li>
  <li>以上で、めでたく信頼されていることになりました。あれ、何だか偽りの愛みたいですね。<br /><a href="http://wpxtreme.jp/cms/wp-content/uploads/2011/10/11103105.jpg"><img src="http://wpxtreme.jp/cms/wp-content/uploads/2011/10/11103105-620x403.jpg" alt="" title="11103105" width="620" height="403" class="alignnone size-large wp-image-765" /></a></li>
<h4>登録してみよう</h4>
<p>おー！登録できた！！WordPress Rocks&hearts; とかなんとか言っとる！やっほー！！！<br />
<a href="http://wpxtreme.jp/cms/wp-content/uploads/2011/10/11103106.jpg"><img src="http://wpxtreme.jp/cms/wp-content/uploads/2011/10/11103106.jpg" alt="Register Versions: Thanks for registering. You ROCK!" title="11103106" width="336" height="259" class="alignnone size-full wp-image-786" /></a></p>
<h4>CONCLUSION</h4>
<ul>
  <li>後でやってもダメなのに "Please try again later." とか表示しない。</li>
  <li>メンドくさいことになるくらいなら、オンライン登録とか小難しいことに挑戦しない。</li>
  <li>メールでチマチマ対応してないで FAQ で詳細に説明しとこう。</li>
</ul>
<p>ちなみにこの Versions を開発したのはミニマルだかシンプルだかのネタでよく紹介されていた <a href="http://www.madebysofa.com/archive/">We are Sofa</a> の皆さんですが、目立ったせいで Facebook に取り込まれてしまい <a href="http://www.madebysofa.com/">WE WERE SOFA</a> になってしまいました。翔丸組に入るんだ、的なアレですね。Facebook はヤワじゃねぇ。<h5>動作確認バージョン</h5><ul class="tested-vers"><li>Versions 1.1.8</li><li>Mac OSX 10.5.8</li><li>Safari 5.0.6</li></ul>]]></content:encoded>
			<wfw:commentRss>http://wpxtreme.jp/versions-how-to-solve-the-registration-probrem/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://wpxtreme.jp/versions-how-to-solve-the-registration-probrem" />
	</item>
		<item>
		<title>WordPress で Ajax：コメント取得編</title>
		<link>http://wpxtreme.jp/get-comments-by-ajax-in-wordpress</link>
		<comments>http://wpxtreme.jp/get-comments-by-ajax-in-wordpress#comments</comments>
		<pubDate>Wed, 26 Oct 2011 08:02:31 +0000</pubDate>
		<dc:creator>kz</dc:creator>
				<category><![CDATA[TUTORIALS]]></category>
		<category><![CDATA[action]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[comment]]></category>
		<category><![CDATA[modifications]]></category>

		<guid isPermaLink="false">http://wpxtreme.jp/?p=669</guid>
		<description><![CDATA[元ネタはお馴染み <a href="http://ja.forums.wordpress.org/">WordPress フォーラム</a> から「<a href="http://ja.forums.wordpress.org/topic/8202">コメントの表示スクリプト</a>」です。コメントを新着順に数件表示しておいて、全部読みたい方には［全部読む］ボタンをクリックしてもらおうという作戦です。wpxtreme 的にはページネーションとかチラ見せはメンドくさいので全部見せといたらええやん！と思いますが、こういった需要は多いハズなのでやってみます。記事書きながらのカスタマイズです、できるかな。<a class="excerpt-more" href="http://wpxtreme.jp/get-comments-by-ajax-in-wordpress">Continue Reading &#187;</a>]]></description>
			<content:encoded><![CDATA[<div class="append"><p>ご要望により、コメントの表示形式を以下の 3タイプご用意いたしました。</p>
<ol>
  <li>コメント全部表示</li>
  <li>始めから指定件数分表示</li>
  <li>2. の残りを表示</li>
</ol>
</div>

<h4>コメント表示の仕組みは TwentyEleven に倣います</h4>
<ol>
  <li>single.php に<br />
    <pre><code>&lt;?php comments_template( '', true ); ?&gt;</code></pre>
    と書く。
  </li>
  <li>テーマに comments.php を用意しておく。</li>
  <li>comments.php 内に<br />
    <pre><code>wp_list_comments( array( 'callback' =&gt; 'twentyeleven_comment' ) );</code></pre>
    のように書いて、各コメントの表示はコールバック関数にお任せする。このコールバックは皆様オリジナルのものでも良いです。<a href="http://wpdocs.sourceforge.jp/%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%82%BF%E3%82%B0/wp_list_comments">Codex</a> には非推奨って書いてあって何かコワいですけど <a href="http://codex.wordpress.org/Template_Tags/wp_list_comments">本家 Codex</a> では Use with caution なので、コールバックの意味をわかってて使うなら何も問題ないです。っていうか知らんでも問題ないよ大丈夫◎
  </li>
</ol>
<p>これ、基本形ね。</p>
<h4>コメントの表示をコントロールするには</h4>
<p>始めに5件だけ表示しておくなら［管理画面｜設定｜ディスカッション］で</p>
<pre><code>1ページあたり［5］件のコメントを含む複数ページに分割し、［最後］のページをデフォルトで表示する </code></pre>
<p>にしとけば OK ◎ ついでに、新しいコメントから表示しないと変なので</p>
<pre><code>［新しい］コメントを各ページのトップに表示する</code></pre>にしましょう。って、これだと全然 OK じゃないぞ。</p>
<p>フォーラムでもコメントされているように</p>
<pre><code>6件コメントがあると、最初の表示で1件、次のページで5件とかっこ悪い表示になってしまう</code></pre>
<p>ので何とかします。</p>
<p>コメントの表示に使ってる <code>wp_list_comments()</code> ですが、実はこの wp_list_なんちゃら の一覧表示系関数には独自の Walker を指定することができます。Walker っていうのは一覧する項目をひとつづつテクテク辿って表示してくれるかわいいヤツです。コメントの場合は Walker_Comment クラス（wp-includes/comment-template.php）がソレですね。これを拡張してオリジナルの Walker をババーッと作ってしまえば、フィルターでチマチマ表示をカスタマイズする必要も無くなります。</p>
<h4>オレ様 Walker を作ろう</h4>
<p>何でもそうですけど、モノを作るときは使う側の立場で作りましょう。作る側の都合で作るとロクなものはできません。ということで、オレ様 Walker を使う場合に</p>
<pre><code>wp_list_comments( array( 
  'callback' =&gt; 'twentyeleven_comment',
  'walker' =&gt; new My_Walker_Comment,  // これがオレ様 Walker
  'display' =&gt; 'initial',  // 未指定か initial で始めから指定件数分、rest で残り全部、all で始めから全部を表示します
) );</code></pre>
<p>みたいに書きさえすれば、後は良きにはからってくれるよう頑張って作ります。始めの5件とか表示のときは display パラメータ無しか 'initial' 指定で OK。残り全部のコメントを表示するときに display パラメータを 'rest' にします。</p>
<div class="append">
<p>カテゴリーによってコメントを全表示にしたり、チラ見せしたりを切り替えるなら以下のようにします。</p>
<pre><code>wp_list_comments( array( 
  'callback' =&gt; 'twentyeleven_comment',
  'walker' =&gt; new My_Walker_Comment,  // これがオレ様 Walker
  'display' =&gt; in_category( 全表示したいカテゴリの ID, スラッグ, 名前等 ) ? 'all' : 'initial', 
) );</code></pre>
</div>

<p>てことでオレ様 Walker ができましたのでテーマの funcrions.php に以下をペッとしてください。長いけど、オリジナルの paged_walk() をちょこっとイジッただけです。</p>
<pre><code>&lt;?php
class My_Walker_Comment extends Walker_Comment {
  function paged_walk( $elements, $max_depth, $page_num, $per_page ) {
    /* sanity check */
    if ( empty($elements) || $max_depth &lt; -1 )
      return '';

    $args = array_slice( func_get_args(), 4 );
    $output = '';

    $id_field = $this-&gt;db_fields['id'];
    $parent_field = $this-&gt;db_fields['parent'];

    if ( !empty($args[0]['reverse_top_level']) )
      $elements = array_reverse( $elements );

    $per_page = (int)$per_page;
    if ( 0 == $per_page )
      $per_page = get_option( 'comments_per_page' );
    $count = -1;
    $total_top = count( $elements );
    $paging = $total_top &gt; $per_page;
		
　  $display = 'initial';
      if ( ! empty( $args[0]['display'] ) )
        $display = $args[0]['display'];
			
      switch ( $display ) {
        case 'initial':
          $start = 0;
          $end   = $per_page;
          break;
        case 'rest':
          $start = $paging ? $per_page : $total_top;
          $end   = $total_top;
          break;
        default: // 'all'
          $start = 0;
          $end   = $total_top;
	  break;
    }

    // flat display
    if ( -1 == $max_depth ) {
      $this-&gt;max_pages = $paging ? 2 : 1;
      $empty_array = array();
      foreach ( $elements as $e ) {
        $count++;
        if ( $count &lt; $start )
          continue;
        if ( $count &gt;= $end )
          break;
        $this-&gt;display_element( $e, $empty_array, 1, 0, $args, $output );
      }
      return $output;
    }
      
    $top_level_elements = array();
    $children_elements  = array();
    foreach ( $elements as $e) {
      if ( 0 == $e-&gt;$parent_field )
        $top_level_elements[] = $e;
      else
        $children_elements[ $e-&gt;$parent_field ][] = $e;
    }

    $total_top = count( $top_level_elements );
    $paging = $total_top > $per_page;
    $this-&gt;max_pages = $paging ? 2 : 1;
		
      switch ( $display ) {
        case 'initial':
          $start = 0;
          $end   = $per_page;
          break;
        case 'rest':
          $start = $paging ? $per_page : $total_top;
          $end   = $total_top;
          break;
        default: // 'all'
          $start = 0;
          $end   = $total_top;
	  break;
    }

    if ( !empty($args[0]['reverse_children']) ) {
      foreach ( $children_elements as $parent =&gt; $children )
        $children_elements[$parent] = array_reverse( $children );
    }

    foreach ( $top_level_elements as $e ) {
      $count++;

      if ( $end &gt;= $total_top &#038;& $count &lt; $start )
        $this-&gt;unset_children( $e, $children_elements );

      if ( $count &lt; $start )
        continue;

      if ( $count &gt;= $end )
        break;

      $this-&gt;display_element( $e, $children_elements, $max_depth, 0, $args, $output );
    }

    if ( $end &gt;= $total_top &#038;& count( $children_elements ) &gt; 0 ) {
      $empty_array = array();
      foreach ( $children_elements as $orphans )
        foreach( $orphans as $op )
          $this->display_element( $op, $empty_array, 1, 0, $args, $output );
    }

    return $output;
  }
}?&gt;</code></pre>
<p>なお、パーマリンクでのコメントページ指定 /comment-page-1/ とかは一切無視しています。</p>
<h4>［すべてのコメントを表示］ボタンを作る</h4>
<p>comments.php で display パラメータ無しか 'initial' の <code>wp_list_comments()</code> を書いた下辺りに以下のコードを書きます。</p>
<p class="append">カテゴリーによってコメントを全表示にしたりする場合は、始めの if 文に条件を追加します。</p>
<pre><code>&lt;?php if ( get_comment_pages_count() &gt; 1 ) : ?&gt;
&lt;?php 
/* カテゴリーによって全表示とかする場合は、こっちの書き方で！
if ( get_comment_pages_count() &gt; 1 &amp;&amp; ! in_category( 全表示するカテゴリの ID, スラッグ, 名前等 ) ) : 
*/
?&gt;
&lt;div id="get-rest-of-comments"&gt;&lt;a href="#"&gt;すべてのコメントを表示&lt;/a&gt;&lt;/div&gt;
&lt;script type='text/javascript'&gt;
//&lt;![CDATA[ 
jQuery(document).ready( function($) {
  $('#get-rest-of-comments a').click( function() {
    $(this).replaceWith('&lt;span class="loading"&gt;Loading...&lt;/span&gt;');
	
    $.post( '&lt;?php echo site_url(); ?&gt;', {
        get_rest_of_comments: 1,
        post_id: &lt;?php echo get_the_ID(); ?&gt;
      }, function(data) {
        $('#get-rest-of-comments').remove();
        $('#comments .commentlist').append(data); // 各コメントの li 要素の親まで辿って append してね！
      }
    );
	
    return false;
  });
});
//]]&gt;
&lt;/script&gt;
&lt;?php endif; ?&gt;
</code></pre>
<p>簡単に説明すると、</p>
<ol>
  <li>表示し切れてないコメントの残りがあるなら、</li>
  <li>［すべてのコメントを表示］リンクを表示して、</li>
  <li>ソレがクリックされたら、</li>
  <li>リンクを「Loading...」に変更して、</li>
  <li>get_rest_of_comments という合い言葉と記事 ID をパラメータにして Ajax !</li>
  <li>残りのコメントを取得したら余計なものは削除して、</li>
  <li>コメントの最後に追加します。</li>
  <li>あぁっ！このクリックは無かったことにしといてね！</li>
</ol>
<p>てな感じです。</p>
<h4>Ajax で残りのコメント全部を取得する</h4>
<p>テーマの functions.php に以下をペッとします。</p>
<pre><code>&lt;?php
add_action( 'init', 'my_ajax' );
function my_ajax() {
  if ( ! isset( $_POST['get_rest_of_comments'] ) )
    return;

  if ( 'XMLHttpRequest' == $_SERVER['HTTP_X_REQUESTED_WITH'] ) {
    @header('Content-Type: text/html; charset=' . get_option( 'blog_charset' ) );

    $post_id = (int) $_POST['post_id'];
		
    $GLOBALS['post'] = get_post( $post_id );
		
    $comments = get_comments( array(
      'post_id' =&gt; $post_id, 
      'status' =&gt; 'approve', 
      'order' =&gt; 'ASC',
    ) );
    
    wp_list_comments( array( 
      'callback' =&gt; 'twentyeleven_comment',
      'walker' =&gt; new My_Walker_Comment,
      'display' =&gt; 'rest',
      ), $comments );
  }
	
  exit();
}
?&gt;</code></pre>
<p>管理画面じゃない（通常の公開画面？）からの Ajax は <code>init</code> アクションで処理しましょう。</p>
<p>簡単に説明すると、</p>
<ol>
  <li>get_rest_of_comments の合い言葉が POST されてないなら無視！</li>
  <li>Ajax だったら処理します。</li>
  <li>POST された記事 ID でもって、</li>
  <li>現在の post を設定しておいて、</li>
  <li>その記事のコメントを取得する。</li>
  <li>残りのコメントを表示します。</li>
  <li>さいなら！</li>
</ol>
<p>てな感じです。<code>wp_list_comments()</code> で表示しちゃってる内容が、先ほどの Ajax な POST</p>
<pre><code>$.post( url, parameters, function(data) {} )</code></pre>
<p>の結果として data に入ってきます。</p>
<h4>CONCLUSION</h4>
<ul>
  <li>一覧表示系関数の出力をイジるなら、オリジナルの Walker を作るのがイマどき。</li>
  <li>公開画面側の Ajax 処理の POST 先 URL はサイトの URL でいいよ。</li>
  <li>公開画面側の Ajax 処理は init アクションでやってしまおう。</li>
  <li>公開画面側の Ajax 処理には「何の処理をするか」の合い言葉を POST してあげよう。</li>
  <li>コメントは始めから全部表示しといたらいいと思うよ。</li>
</ul><h5>動作確認バージョン</h5><ul class="tested-vers"><li>WordPress 3.1.3</li></ul>]]></content:encoded>
			<wfw:commentRss>http://wpxtreme.jp/get-comments-by-ajax-in-wordpress/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://wpxtreme.jp/get-comments-by-ajax-in-wordpress" />
	</item>
		<item>
		<title>WordPressテーマのfunctions.phpをクラス化する</title>
		<link>http://wpxtreme.jp/use-class-in-wordpress-theme</link>
		<comments>http://wpxtreme.jp/use-class-in-wordpress-theme#comments</comments>
		<pubDate>Mon, 01 Aug 2011 10:14:02 +0000</pubDate>
		<dc:creator>kz</dc:creator>
				<category><![CDATA[TUTORIALS]]></category>
		<category><![CDATA[class]]></category>
		<category><![CDATA[theme]]></category>

		<guid isPermaLink="false">http://wpxtreme.jp/?p=630</guid>
		<description><![CDATA[プラグインを作成するとき、まるっとクラス化することで 関数名のコンフリクトの心配やら、ちまちまプレフィックスをつける面倒から解放されます。じゃぁテーマの functions.php でも同じことができるんではないか 。子テーマとか考えると function_exists() での判定やら、親テーマと同じプレフィックス付きの長い関数名やら、なんちゅう読み難いんじゃー、といった諸々から解放されてもっと幸せになれるんではないか。そんな思いからテーマ（のfunctions.php）をクラス化する方法を考えてみました。何十個も twentyeleven_ とか書くのシンドイ。<a class="excerpt-more" href="http://wpxtreme.jp/use-class-in-wordpress-theme">Continue Reading &#187;</a>]]></description>
			<content:encoded><![CDATA[<p>#prefix ってプリフィクスじゃないのね。。。</p>
<h4>親テーマ</h4>
<p>Web 制作会社なら（そうでなくても）自社ルールに則って構築されたテーマのひな形が存在すると思います。無い場合は、この際だから作ってしまいましょう！いつまでもまんま TwentyTen でいいハズないじゃない。そういうテーマを自社の親テーマにして、各々のクライアントにフィットさせた子テーマを納品するようにすると制作効率が向上したりテーマ管理がし易くなったり彼女ができたりと色々ステキです。<br />
そんなわけで、以下 テーマ（の functions.php）をクラス化して子テーマも使う場合の最少コード例です。</p>
<h5>親テーマの style.css</h5>
<p>正規の親テーマの書き方と同じです。</p>
<pre><code>/*
Theme Name: Wpxtreme Parent
Theme URI: http://wpxtreme.jp/
Author: kz
Author URI: http://kzxtreme.com/
Description: 当社の親テーマであります
Version: 1.0
*/
/* スタイルの記述は省略 */</code></pre>
<h5>親テーマの functions.php</h5>
<p>ポイントは、<code>after_setup_theme</code> アクションの優先度です。functions.php は 子テーマ ---> 親テーマ の順に読み込まれますが、アクションの優先度により 親テーマのクラス定義 ---> 子テーマのクラス定義 の順に実行されるように指定します。で、最後に現在のテーマのクラスのオブジェクトを作って完了です。ののの気になる。<br />
PHP 的なポイントは <code>new static()</code> 辺り。この、親クラスに書いてるけど「子クラスの」という扱いができる late bind は PHP 5.3.0〜使えます。</p>
<pre><code>&lt;?php
// テーマオブジェクトをグローバル変数にします。
// the_theme なんて危険な名前は避けるといいかもね！
add_action( 'after_setup_theme', 'instantiate_theme', 99999 );
function instantiate_theme() {
  $GLOBALS['the_theme'] = call_user_func( array( str_replace( ' ', '_', get_current_theme() ), 'get_object' ) );
}

// 親テーマは最優先でアクション実行！
add_action( 'after_setup_theme', 'setup_parent_theme', 0 );
function setup_parent_theme() {
  if ( ! class_exists( 'Wpxtreme_Parent' ) ) { // テーマ名のスペースを '_' で置換してクラス名にしましょう！

    class Wpxtreme_Parent {
      static private   $classobj = NULL;

      public function __construct() {
        // construct self
        // add_theme_support(), add_filter(), add_action() などなど
      }

      public static function get_object() {
        if ( NULL === self :: $classobj ) {
          self :: $classobj = new static();
        }
        return self :: $classobj;
      }
    }
  }
}</code></pre>
<h5>子テーマの style.css</h5>
<p>これも正規の子テーマの書き方と同じです。</p>
<pre><code>/*
Theme Name: Wpxtreme Child
Theme URI: http://wpxtreme.jp/
Author: kz
Author URI: http://kzxtreme.com/
Description: クライアントA様向けテーマです！
Version: 1.0
Template: wpxtremeparent
*/
@import url("../wpxtremeparent/style.css");
/* スタイルの記述は省略 */</pre></code>
<h5>子テーマの functions.php</h5>
<pre><code>&lt;?php
// 親テーマより後にアクション実行！
add_action( 'after_setup_theme', 'setup_child_theme',1 );
function setup_child_theme() {
  if ( ! class_exists( 'Wpxtreme_Child' ) ) {
	
    class Wpxtreme_Child extends Wpxtreme_Parent {
      public function __construct() {
	// construct parent
	parent :: __construct();

        // construct self
        // add_theme_support(), add_filter(), add_action() などなど
      }
    }
  }
}</code></pre>
<p>これだけで OK です。楽チン！ってこれだけじゃ何だかよくわかりませんネ。</p>
<h4>もうちょっと具体的に</h4>
<p>サンプル的にそれらしい処理を書いてみますね。※コードはクラスの定義部分だけです。</p>
<h5>親テーマの functions.php</h5>
<pre><code>class Wpxtreme_Parent {
  static private   $classobj = NULL;
  static protected $domain;  // text domain
  static protected $userdata;  // 'name' =&gt; array( 'label' =&gt; 'label to display', 'type' =&gt; 'text'|'textarea'|..., 'description' =&gt; 'description.' )
  static public $path;  // stylesheet directory uri
  /**
   * Constructor, init on defined hooks of WP and include second class
   *
   * @access public
   * @since 0.0.1
   * @uses add_filter, add_action
   * @return void
   */
  public function __construct() {
    // member variables
    self :: $domain = strtolower( str_replace( '_', '', get_class( $this ) ) );
    self :: $path = get_stylesheet_directory_uri();
	
    load_theme_textdomain( self :: $domain, TEMPLATEPATH . '/languages' );
    
    // supports
    add_editor_style();
    add_theme_support( 'post-thumbnails' );

    // user profile
    add_filter( 'user_contactmethods', array( $this, 'user_contactmethods' ) );
    if ( isset( self :: $userdata ) ) {
      add_action( 'personal_options_update', array( $this, 'update_profile' ) );
      add_action( 'edit_user_profile_update', array( $this, 'update_profile' ) );
      add_action( 'show_user_profile', array( $this, 'user_profile' ) );
      add_action( 'edit_user_profile', array( $this, 'user_profile' ) );
    }
  }
  /**
   * Handler for the action 'init'. Instantiates this class.
   *
   * @access public
   * @since 0.0.1
   * @return object $classobj
   */
  public static function get_object() {
    if ( NULL === self :: $classobj ) {
      self :: $classobj = new static();
    }
    return self :: $classobj;
  }
  /**
   * Delete obsolete contact methods.
   *
   * @access public
   * @since 0.0.1
   * @return array $contactmethods
   */
  public function user_contactmethods( $contactmethods ) {
    unset( $contactmethods['aim'] );
    unset( $contactmethods['jabber'] );
    unset( $contactmethods['yim'] ); 
    return $contactmethods;
  }
  /**
   * Update user meta.
   *
   * @access public
   * @since 0.0.1
   * @return void
   */
  public function update_profile( $user_id ) {
    if ( !current_user_can( 'edit_user', $user_id ) )
      return false;

    foreach ( array_keys( (array) self :: $userdata ) as $field )
      update_user_meta( $user_id, $field, $_POST[$field] );
  }
  /**
   * Print form for user profile.
   *
   * @access public
   * @since 0.0.1
   * @return void
   */
  public function user_profile( $user ) {
    if ( !current_user_can( 'edit_user', $user-&gt;ID ) )
      return false;

?&gt;&lt;table class="form-table"&gt;&lt;?php			
    foreach ( (array) self :: $userdata as $name =&gt; $data )
      printf( '&lt;tr&gt;&lt;th&gt;&lt;label for="%1$s"&gt;%2$s&lt;/label&gt;&lt;/th&gt;'
        . '&lt;td&gt;&lt;input type="%3$s" name="%1$s" id="%1$s" value="%4$s" class="regular-text" /&gt;'
        . '&lt;br /&gt;&lt;span class="description"&gt;%5$s&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;',
      esc_attr( $name ),
      esc_html( isset( $data['label'] ) ? $data['label'] : $name  ),
      esc_attr( isset( $data['type' ] ) ? $data['type' ] : 'text' ),
      esc_attr( get_user_meta( $user-&gt;ID, $name, true ) ),
      esc_html( isset( $data['description' ] ) ? $data['description' ] : '' )
    );
?&gt;&lt;/table&gt;&lt;?php
  }
  /**
   * Prints HTML with meta information for the current post-date/time.
   *
   * @access public
   * @since 0.0.1
   * @return void
   */
  public function posted_on() {
    printf( __( '&lt;time class="entry-date" datetime="%1$s" pubdate&gt;%2$s&lt;/time&gt;', self :: $domain ),
      esc_attr( get_the_time() ),
      esc_html( get_the_date() )
    );
  }
}</code></pre>
<h5>子テーマの functions.php</h5>
<pre><code>class Wpxtreme_Child extends Wpxtreme_Parent {
  /**
   * Constructor, init on defined hooks of WP and include second class
   *
   * @access public
   * @since 0.0.1
   * @uses add_filter, add_action
   * @return void
   */
  public function __construct() {
    // set protected variables
    self :: $userdata = array(
      'yakusyoku' =&gt; array( 'label' =&gt; '役職', 'type' =&gt; 'text', 'description' =&gt; '社長、平社員、などを書いて！' ),
    );

    // construct parent
    parent :: __construct();

    // construct $this
  }
  /**
   * Add contact methods.
   *
   * @access public
   * @since 0.0.1
   * @return array $contactmethods
   */
  public function user_contactmethods( $contactmethods ) {
    $contactmethods = parent :: user_contactmethods( $contactmethods ); 
    $contactmethods['skype'] = 'Skype 名';
    $contactmethods['twitter'] = 'Twitter ユーザー名';
    $contactmethods['facebook'] = 'Fecebook ユーザー名';
    return $contactmethods;
  }
  /**
   * Prints HTML with meta information for the current post-date/time and author.
   *
   * @access public
   * @since 0.0.1
   * @return void
   */
  public function posted_on() {
    $user = get_userdata( get_the_author_meta( 'ID' ) );
    printf(  __( '&lt;time class="entry-date" datetime="%1$s" pubdate&gt;%2$s&nbsp;&nbsp;%3$s&lt;/time&gt;%4$s', self :: $domain ),
      esc_attr( get_the_time() ),
      esc_html( get_the_time( get_option( 'date_format' ) ) ),
      esc_html( get_the_time( get_option( 'time_format' ) ) ),
      get_avatar( $user-&gt;user_email, 40, self :: $path . '/images/default.gif' )
    );
  }
}</code></pre>
<p></p>
<ul>
<li>$domain<br />テキストドメインはクラス名を英数小文字にし、'_' を無くしたものです。<br />
親テーマ：wpxtremeparent<br />
子テーマ：wpxtremechild</li>
<li>$userdata<br />子テーマで label, type, description を設定すると、親テーマでプロフィールページに入力欄を追加します。</li>
<li>user_contactmethods()<br />プロフィールページの「連絡先」欄<br />親テーマ：不要な項目を削除<br />子テーマ：新規に項目を追加</li>
<li>posted_on()<br />子テーマで処理をまるっとオーバーライドしてます。<br />
テンプレートファイル内で以下のように使用します。</li>
</ul>
<pre><code>global $the_theme;
$the_theme->posted_on();</code></pre>
<p>ザッと思いつきですが、何かイケてる気がしませんか！？しませんかそうですか。全部 static function でええやんとか色々検討事項はございましょうが、たまにはこんなことを考えてみるのも息抜きになって良いかもですね！</p><h5>動作確認バージョン</h5><ul class="tested-vers"><li>WordPress 3.1.3</li><li>PHP 5.3.5</li></ul>]]></content:encoded>
			<wfw:commentRss>http://wpxtreme.jp/use-class-in-wordpress-theme/feed</wfw:commentRss>
		<slash:comments>20</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://wpxtreme.jp/use-class-in-wordpress-theme" />
	</item>
		<item>
		<title>query_posts, get_posts で複数の order 指定に対応する</title>
		<link>http://wpxtreme.jp/multiple-order-parameter-in-query-posts-and-get-posts</link>
		<comments>http://wpxtreme.jp/multiple-order-parameter-in-query-posts-and-get-posts#comments</comments>
		<pubDate>Fri, 29 Jul 2011 05:46:50 +0000</pubDate>
		<dc:creator>kz</dc:creator>
				<category><![CDATA[TIPS]]></category>
		<category><![CDATA[filter]]></category>
		<category><![CDATA[query]]></category>

		<guid isPermaLink="false">http://wpxtreme.jp/?p=615</guid>
		<description><![CDATA[元ネタは公式フォーラムの<a href="http://ja.forums.wordpress.org/topic/7439">カスタムフィールドでソートした後に、日付の降順にしたい</a>です。query_posts(), get_posts() で記事を取得する時に複数の項目でソートしたい、ことはよくあります。WordPress では orderby に半角スペース区切りで並び替えのキーとなる複数の項目を指定することができますが、昇順降順の order パラメータには ASC, DESC のどちらか1つしか指定できない仕様になっています。バグなハズはない。きっと深いワケがあるハズ。とはいえ、項目ごとに並び順を指定する方が需要は多いハズなのでやってみましょう！<a class="excerpt-more" href="http://wpxtreme.jp/multiple-order-parameter-in-query-posts-and-get-posts">Continue Reading &#187;</a>]]></description>
			<content:encoded><![CDATA[<p>※ order も複数指定できるよ、って話を以前どこかで見た気がするけど仕様変更されたのかしら。</p>
<h4>コアのソースを見てみよう</h4>
<p><code>query_posts()</code> や素の <code>get_posts()</code> は </code>WP3.2.1 wp-includes/query.php <code>WP_Query::&amp;get_posts()</code> を呼んでます。で、当該処理は以下のようになってます。</p>
<pre><code>if ( empty($q['order']) || ((strtoupper($q['order']) != 'ASC') &#038;& (strtoupper($q['order']) != 'DESC')) )
  $q['order'] = 'DESC';  // ■order は ASC か DESC じゃなければ DESC になります

// Order by
if ( empty($q['orderby']) ) {
  $orderby = "$wpdb->posts.post_date " . $q['order'];
} elseif ( 'none' == $q['orderby'] ) {
  $orderby = '';
} else {
  // Used to filter values
  $allowed_keys = array('author', 'date', 'title', 'modified', 'menu_order', 'parent', 'ID', 'rand', 'comment_count');
  if ( !empty($q['meta_key']) ) {
    $allowed_keys[] = $q['meta_key'];
    $allowed_keys[] = 'meta_value';
    $allowed_keys[] = 'meta_value_num';
  }
  $q['orderby'] = urldecode($q['orderby']);
  $q['orderby'] = addslashes_gpc($q['orderby']);

  $orderby_array = array();
  foreach ( explode( ' ', $q['orderby'] ) as $i =&gt; $orderby ) {  // ■orderby は半角スペース区切り！
    // Only allow certain values for safety
    if ( ! in_array($orderby, $allowed_keys) )
      continue;

    switch ( $orderby ) {
      case 'menu_order':
          break;
      case 'ID':
          $orderby = "$wpdb-&gt;posts.ID";
          break;
      case 'rand':
          $orderby = 'RAND()';
          break;
      case $q['meta_key']:
      case 'meta_value':
           $orderby = "$wpdb-&gt;postmeta.meta_value";
           break;
      case 'meta_value_num':
           $orderby = "$wpdb-&gt;postmeta.meta_value+0";
           break;
      case 'comment_count':
           $orderby = "$wpdb-&gt;posts.comment_count";
           break;
      default:
           $orderby = "$wpdb-&gt;posts.post_" . $orderby;
    }

    $orderby_array[] = $orderby;
  }
  $orderby = implode( ',', $orderby_array ); // ■orderby パラメータを半角コンマで連結

  if ( empty( $orderby ) )
    $orderby = "$wpdb-&gt;posts.post_date ".$q['order']; // ■orderby 指定が無効な場合は日付の降順
  else
    $orderby .= " {$q['order']}";  // ■最後に order パラメータを追加
}</code></pre>
<p>ポイントとなる箇所にコメントを記載してます。これで、</p>
<ul>
<li>order は ASC, DESC どちらか1つのみ</li>
<li>orderby は半角スペース区切りで複数指定可能</li>
<li>order パラメータは半角コンマ区切りで連結した orderby の最後に追加される</li>
</ul>
<p>という現状把握ができました。</p>
<h4>フィルタで ORDER BY 節をいじろう</h4>
<p>節はブシじゃないですよ。<code>WP_Query::&amp;get_posts() </code>ではSQL 文の各節ごとにフィルタが用意されているので書き換えは簡単です。</p>
<pre><code>if ( !$q['suppress_filters'] ) { // ■get_posts() はこれがデフォルトで true！
  $where        = apply_filters_ref_array( 'posts_where_paged',    array( $where, &#038;$this ) );
  $groupby    = apply_filters_ref_array( 'posts_groupby',        array( $groupby, &#038;$this ) );
  $join        = apply_filters_ref_array( 'posts_join_paged',    array( $join, &#038;$this ) );
  $orderby    = apply_filters_ref_array( 'posts_orderby',        array( $orderby, &#038;$this ) ); // ■これを使う！
  $distinct    = apply_filters_ref_array( 'posts_distinct',    array( $distinct, &#038;$this ) );
  $limits        = apply_filters_ref_array( 'post_limits',        array( $limits, &#038;$this ) );
  $fields        = apply_filters_ref_array( 'posts_fields',        array( $fields, &#038;$this ) );

  // Filter all clauses at once, for convenience
  $clauses = (array) apply_filters_ref_array( 'posts_clauses', array( compact( $pieces ), &#038;$this ) );
  foreach ( $pieces as $piece )
     $$piece = isset( $clauses[ $piece ] ) ? $clauses[ $piece ] : '';
}</code></pre>
<p><code>suppress_filters</code> というパラメータはその名の通り、<code>true</code> に設定されているとフィルタを実行しません。<code>WP_Query::&amp;get_posts()</code> や <code>query_posts()</code> を使うときは敢えて <code>true</code> を指定しない限り <code>false</code> になるので何も心配しなくてもフィルタ実行してくれます。が、<code>get_posts()</code> という素の関数ではデフォルトパラメータとしてこれが <code>true</code> という仕様なのでフィルタを使用したい場合は <code>false</code> を明示的に指定します。以下にまとめますね。</p>
<pre><code>// 気にしなくて OK！
query_posts( array(  'orderby' =&gt; 'date',  'order' =&gt; 'ASC' ) );

/ /気にしなくて OK！
$posts = new WP_query( array(  'orderby' =&gt; 'date',  'order' =&gt; 'ASC' );

// 気にしなくて OK！
$my_query = new WP_query();
$posts = $my_query-&gt;get_posts(  array( 'orderby' =&gt; 'date',  'order' =&gt; 'ASC' ) );

// 気にして！false にして！
$posts = get_posts(  array( 'orderby' =&gt; 'date',  'order' =&gt; 'ASC',  'suppress_filters' =&gt; false ) );</code></pre>
<h5>order パラメータの与え方</h5>
<p>さて、<code>order</code> に複数パラメータを与えて <code>posts_orderby</code> フィルタで ORDER BY 節を変更したいところですが、このフィルタが呼ばれるのは、先ほどのソースの一番上のコメント部分「 ■order は ASC か DESC じゃなければ DESC になります」より後なので、複数パラメータを与えても既に <code>DESC</code> に変えられてます。<br />
なので、ここでは別のパラメータ <code>myorder</code> を創作してそれに複数 <code>order</code> を指定するようにします。以下、パラメータの与え方。</p>
<pre><code>// 例）メタキー my_meta の値で降順  --&gt; 日付で降順にする場合
$args = array(
    'meta_key' => 'my_meta',
    'orderby' => 'meta_value_num date',
    'myorder' => 'DESC DESC',  // ■創作パラメータ
   // 'suppress_filters' =&gt; false,  // ■素の get_posts() で使う場合はこれも必要！
);
query_posts( $args );
 ：
</code></pre>
<h5>フィルタの処理</h5>
<p>以下を functions.php に追加すれば OK です。</p>
<pre><code>add_filter( 'posts_orderby','my_posts_orderby', 10, 2 );
function my_posts_orderby( $orderby, $query ) {
    $orders = explode( ' ', strtoupper( $query-&gt;get( 'myorder' ) ) );
    if ( 0 < count( $orders ) ) {  // ■myorder にパラメータが設定されている場合：
        $orderby_array = array();
        foreach ( explode( ',', str_replace( ' DESC', '', $orderby ) ) as $i => $the_orderby ) { // ■最後の DESC を取って半角カンマで項目を分割
            if ( ! isset( $orders[$i] ) || ! in_array( $orders[$i], array( 'ASC', 'DESC') ) ) // ■ASC, DESC 以外の場合：
                $orderby_array[] = $the_orderby . ' DESC' ; // ■DESC にする
            else // ■ASC または DESC なら：
                $orderby_array[] = $the_orderby . ' ' . $orders[$i];  // ■項目の直後に並び順を追加
          }
          $orderby = implode( ',', $orderby_array ); // ■並び順が追加された項目達を連結
    }
    return $orderby; // ■いってらっしゃい！
}</code></pre>
<h5>動作確認バージョン</h5><ul class="tested-vers"><li>WordPress 3.1.3</li></ul>]]></content:encoded>
			<wfw:commentRss>http://wpxtreme.jp/multiple-order-parameter-in-query-posts-and-get-posts/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
	<xhtml:link rel="alternate" media="handheld" type="text/html" href="http://wpxtreme.jp/multiple-order-parameter-in-query-posts-and-get-posts" />
	</item>
	</channel>
</rss>

