先日、WordPressのユーザーコミュニティである『WordBench』にて「ループ」をテーマにした約4時間のハンズオンセミナーを行いました。4時間、ループのことしかやらない勉強会はWordBenchでも異色だと思うのですが、参加された方の感想はおおむね好評だったようです。公式ドキュメントのCodex日本語版の「The Loop」の項が未翻訳というのも理由の一つかもしれません。
さて、WordPressカスタマイズのキモともいえるこのループ。私もかつて解説本から学んだとおり、
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <!-- 記事があるときの表示内容をここに書く --> <?php endwhile; else : ?> <!-- 記事がないときの表示内容をここに書く --> <?php endif; ?>
てな感じでしゃしゃっと書いています。WordPressを始める前にMovableTypeをちょっとかじったこともあり、ループについて「あーそんなもんかー」という感覚で、疑問も抱かずやっていたのですね。
で、今回の勉強会をやるにあたって、はたと思ったのです。「if とか while が条件分岐ってのはわかるけど、この the_post() ってのはそもそも何をしてるヤツなんだ?」と。
そう思ってググってみたものの the_post() に関する記事がほとんど見つからないという現実が。頼みのCodexも未翻訳状態で残念なことになっている。うむ、それならひとつ、学習をかねてやってみようじゃありませんか……ということでこのエントリーを起こすことにしました。
WordBenchを運営してるくせに実はよくわかってない点も多々ありますので、そのあたりはバシバシつっこんでいただければ幸いに存じます。では始めていきましょう。
超・ミニマムなテーマを有効化する
ループの構造をわかりやすくするため、最低限の要素しか記述していないテーマをつくりました。index.php と style.css だけのテーマ『Skeleton』です。よろしければ、以下よりダウンロード→サーバにアップロード→有効化してみてください。
ループの基本構造をもうちょっとほどいてみよう
『Skeleton』の index.php をひらいてみてください。ループのスタートを示す11行目の記述です。
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
いきなり「あちゃー」な感じですね。個人的にはこの1行が、ループに対する苦手意識の第一歩じゃないかと思うので、もうちょっとほどいてみることにします。プログラマーさんなら「こんな書き方エレガントじゃないヤイヤイ!」とおっしゃることでしょうが、そこは母ちゃん勘弁イデデデデ。
ついでに、記事がないときの処理を省いて(実際にはちゃんと書いてね)さらにループを簡潔にしてみましょう。『Skeleton』の10~17行目を次のように書き換えてみます。
<ul> <?php if ( have_posts() ) : ?> <?php while ( have_posts() ) : ?> <?php the_post(); ?> <li><?php the_title(); // 記事のタイトルを表示 ?></li> <?php endwhile; ?> <?php endif; ?> </ul>
このように見ると、ループは if ~ endif が while ~ endwhile を包み込む、二重の構造でできていることが分かります。
そもそも if ~ endif と while ~ endwhile がやっていることって?
ここで改めて if ~ endif, while ~ endwhile の動作についてふれておきましょう。ともにPHPで利用可能な制御構造の仕組みで、PHPのプログラム内で次のような振る舞いをします。
- if ~ endif……if に与えられた条件が満たされる場合 if ~ endif の間の処理を行う
- while ~ endwhile……while に与えられた条件が満たされる場合 while ~ endwhile の間の処理を繰り返し行う
この制御構造をWordPressのループに当てはめてみます。ループ内に2回出てくる have_posts() は「表示できる記事がある」ことを示す印のようなものだと考えてください。have_posts() は if, while 双方に条件として与えられているので、上記をふまえるとWordPressのループでは
- if ~ endif……表示できる記事がある場合 if ~ endif の間の処理を行う
- while ~ endwhile……表示できる記事がある場合 while ~ endwhile の間の処理を繰り返し行う
ということになります。
繰り返しの条件を与えないと while ~ endwhile は働いてくれない
「表示できる記事がある場合」という条件は同じながら if ~ endif と while ~ endwhile の処理には、実は大きな違いがあります。while ~ endwhile の説明をもう一度ご覧ください。「繰り返し」という表現を強調しているのがお分かりいただけるでしょうか。
その理解を深めていただくため、PHPマニュアルの while の項よりこのようなサンプルコードを引用してみます。while ~ endwhile を用いて同じ処理を10回繰り返し、1から10までを表示するコードです。
$i = 1; while ($i <= 10): echo $i; $i++; endwhile;
《コード解説》
1行目……while ~ endwhile に入る前に、表示すべき数字(=処理を繰り返した回数)を $i という箱(PHPでは「変数」といいます)に入れます。
2行目……while で「$i が10以下の場合」という条件を判断。1行目の記述により、そのまま while ~ endwhile のループに入ります。
3行目……$i の内容を表示( 1 が表示されます)。
4行目……$i の数値を 1 加算( $i の値が 2 となります)。
5行目……ループ終了。
その後処理は2行目に戻り $i の値が 2 であることから2回目のループに入っていきます。以降 $i の値が 10 になるまで処理が繰り返されるというわけです。
さて、このコードでたいへん重要な役割を果たしているのが、$i をカウントアップしている
$i++;
の1行。これがないと $i の値は 1 のままなので何度ループしても「$i が10以下の場合」の条件が変わらず
111111111111111111111111111...
と、終わりのない表示結果となってしまいます。これらのことから while ~ endwhile においては
- ループの外側で初期値を与える
- ループ内でその値を変える
のが使いこなしのカギとなるのがお分かりいただけるでしょうか。
the_post() がないとループはどうなる?
前フリが長くなりましたが、ようやく the_post() の話にたどりつきました。
これまでの説明をふまえて、『Skeleton』テーマから試しに the_post() を外して実行してみます。
<?php if ( have_posts() ) : ?> <?php while ( have_posts() ) : ?> <li><?php the_title(); // 記事のタイトルを表示 ?></li> <?php endwhile; ?> <?php endif; ?>
なんということでしょう。最初の記事のタイトルだけがただただ表示されて、終わりのない状態になってしまったではありませんか(ブラウザの「読み込み停止」をクリックすれば中止できます)。
そうです。the_post() にはループ内で値をカウントアップする役割があるのです。Codexを見ても、解説書を読んでも、the_post() についてはサラリと触れられているに過ぎませんが、実は実はとんでもなくたいへんな役割をもっている重要なキャラだったのでありました。
the_post() の下地を作る $wp_query
さきほど while ~ endwhile においては
- ループの外側で初期値を与える
- ループ内でその値を変える
のが使いこなしのカギとなることを書きました。ということはWordPressでも、ループの外側で何らかの初期値が与えられ、ループ内で the_post() がその値を加減算していると推測できます。ループを成り立たせるために、どんな値が動いているのでしょう?
カギを握っているのは、$wp_query という隠れた変数です。この変数は、WordPressのプログラム側であらかじめ「予約」されているものなので、テンプレートなどで同じ名前の変数を作っちゃうとエラいことに。まぜるな危険。
で、『Skeleton』テーマを有効化した状態でサイトトップ(index.php)にアクセスしたとき、WordPressのプログラムは $wp_query にこんな情報を入れてくれます(ものすごく端折ってるので、ほかにもいっぱいいろいろ入ってる)。
- 投稿10件分のタイトルや本文、作成日・更新日など(投稿には0~9の連番がふられてます)
- そのうち、最初の投稿のタイトルや本文、作成日・更新日など
- $wp_query に入っている記事の件数(10)
- ループカウンタ(ループ外にいることから初期値 -1 が入ってます)
※1, 3の内容は、管理パネルの[設定]-[表示設定]-[1ページに表示する最大投稿数]の設定により変わります
変数にはずーっと上で示した $i のように単一の値だけでなく、上記のようなたくさんの情報を詰め込むこともできます(ここを詳しく説明するとPHPの話になるので「変数とはそういうものだ」ってくらいの認識でOKです)。
n番目の記事を表示するとき、ループカウンタはn-1になっている
これをふまえてループの流れを見ていきましょう。まずは、if, while の双方で出てくる have_posts() の役割です。have_posts() は上記1~4の情報をもとに次のような動作をします(ほかにもあるけど省略)。
- ループカウンタ + 1 < $wp_query 内の記事件数 なら true(真)を返す
- ループカウンタ + 1 = $wp_query 内の記事件数 かつ $wp_query 内の記事件数 > 0 なら false(偽)を返す
上記より if ( have_posts() ) は「真」となるので、こんどは while ( have_posts() ) の判断に入ります。ループ1回目では if ( have_posts() ) と同じ条件なので、繰り返し処理に入ってもOKですね。
ということでループ1回目の the_post() さんは、こんな振る舞いをします(ほかにもあるけど省略)。
- ループカウンタを 1 加算する(0 になる)
- 10件の投稿のうち連番 0 の投稿を表示する準備をする
the_post() さんがこのようにお膳立てしてくれたので、ループ内のテンプレートタグ the_title() で連番 0 番目の投稿タイトルが表示できることになります。
それでは2回目の while ( have_posts() ) 。1回目の処理によりループカウンタは 0 ですね。have_posts() の振る舞いより
- ループカウンタ + 1 < $wp_query 内の記事件数
となり while ( have_posts() ) は「真」。2回目のループに入って the_post() の処理はこうなります。
- ループカウンタを 1 加算する(1 になる)
- 10件の投稿のうち連番 1 の投稿(つまり、2番目の投稿)を表示する準備をする
お分かりいただけるでしょうか? n番目の記事を表示する際のループカウンタが n-1 になっていることが。ということで、10回目のループが終わったところでループカウンタが 9 になります。
まだまだ繰り返すヨー、とばかりに11回目のループに入ろうとしても while ( have_posts() ) の箇所で have_posts() の振る舞いである
- ループカウンタ + 1 = $wp_query 内の記事件数 かつ $wp_query 内の記事件数 > 0 なら false を返す
が満たされ while ~ endwhile 内の処理はできずループを抜ける、ということになるわけです。
ループの詳しい挙動は query.php にて
ここまでかいて約4600字。ところどころ冗長な表現になってしまったかもしれませんが the_post() の役割とその大切さを少しでも感じていただけたのでしたら、幸いです。
この記事では have_posts() や the_post() の処理をある程度簡略化して説明しました。PHPのコードを追いながらもう少し詳しく知ってみたい方は wp-includes/query.php をぜひご参照ください。他のメソッド(機能)と連携しながら、さまざまな処理をしていることがお分かりいただけるかと思います。
非常に為になりました! 小骨のようにひっかかっていたので^^;
面白かった|WordPressの the_post() ってそもそも何者? | 鉄王
WordPressの the_post() ってそもそも何者? | 鉄王
WordPressの the_post() ってそもそも何者? http://t.co/UaH4Lk7e
WordPressの the_post() ってそもそも何者? | 鉄王:… http://t.co/mBJ9mbWH
WordPressの the_post() ってそもそも何者? | 鉄王 http://t.co/DXtqvfnj
WordPressの the_post() ってそもそも何者? | 鉄王 http://t.co/r6RmVkLz
WordPressの the_post() ってそもそも何者? | 鉄王 http://t.co/fWJxgsQx #PHP
WordPressの the_post() ってそもそも何者? http://t.co/VlHw8z4J
WordPressの the_post() ってそもそも何者? | 鉄王 http://t.co/KTmQm1WJ
WordPressの the_post() ってそもそも何者? | 鉄王 http://t.co/syoFAki0
WordPressの the_post() ってそもそも何者? | 鉄王 http://t.co/iF7uv9DR
WordPressの the_post() ってそもそも何者? | 鉄王 http://t.co/OV3QUhui
“WordPressの the_post() ってそもそも何者? | 鉄王” http://t.co/7U2AwGO8
[未カテゴリ][MyInterest][WordPress][Web制作][プログラミング][the_post()] / “WordPressの the_post() ってそもそも何者? | 鉄王” http://t.co/Vk6JNNLI
WordPressの the_post() ってそもそも何者? | 鉄王 http://t.co/60kO1Q5h
WordPressの the_post() ってそもそも何者? | 鉄王
http://t.co/aoYBXojN
[*thresh25] WordPressの the_post() ってそもそも何者? | 鉄王 http://t.co/T9H0l9dZ
WordPressの the_post() ってそもそも何者? | 鉄王 http://t.co/CZTbWrNb
WordPressの the_post() ってそもそも何者? | 鉄王 http://t.co/5B4t8bEb
はてな: WordPressの the_post() ってそもそも何者? | 鉄王 http://t.co/d7LCcQlB
コンピュータ・IT: WordPressの the_post() ってそもそも何者? | 鉄王 http://t.co/wGtQ8t6f
WordPressの the_post() ってそもそも何者? | 鉄王 http://t.co/M3zjPx8W
WordPressの the_post() ってそもそも何者? | 鉄王 http://t.co/CVsiKYCu
WordPressの the_post() ってそもそも何者? | 鉄王 http://t.co/BrmVckuT
WordPressの the_post() ってそもそも何者? | 鉄王 http://t.co/A1wsZJMv
覚えたての知識と照らし合わせながら読んだらすごく面白い。WPくらいの大きなプログラムになると、ユーザー定義関数(だよね?)ひとつとっても解読が難しくなるんだなあ。
覚えたての知識と照らし合わせながら読んだらすごく面白い。WPくらいの大きなプログラムになると、ユーザー定義関数(だよね?)ひとつとっても解読が難しくなるんだなあ。 / “WordPressの the_post() ってそもそも何者? …” http://t.co/YYuk5uKH
WordPressの the_post() ってそもそも何者? | 鉄王 http://t.co/1exhWh94
WordPressの the_post() ってそもそも何者? | 鉄王 http://t.co/ypQj4RUf
“WordPressの the_post() ってそもそも何者? | 鉄王” http://t.co/yqnQV2iu
“WordPressの the_post() ってそもそも何者? | 鉄王” http://t.co/9PXInjRj
“WordPressの the_post() ってそもそも何者? | 鉄王” http://t.co/wEvf3Y9d
“WordPressの the_post() ってそもそも何者? | 鉄王” http://t.co/90wJstn9
(43user)(37like)(55tweet)WordPressの the_post() ってそもそも何者? | 鉄王 – http://t.co/oFglxKMe
[WordPress][PHP] / “WordPressの the_post() ってそもそも何者? | 鉄王” http://t.co/GSJNwOlk
the_post()を外したらどうなるのか…疑問に想いテストした事があったから何となく分かってはいたけど、ちゃんとした説明があると、やっぱりいいですね | WordPressの the_post() ってそもそも何者? http://t.co/Y6Ob26j4
“WordPressの the_post() ってそもそも何者? | 鉄王” http://t.co/5Lj826bI
“WordPressの the_post() ってそもそも何者? | 鉄王” http://t.co/m2ZSGm7V
“WordPressの the_post() ってそもそも何者? | 鉄王” http://t.co/wFL94Hyo
3ヵ月ほど前に書いた記事がリツイートされまくりで驚き&感謝 RT @webdesignsokuho: WordPressの the_post() ってそもそも何者? | 鉄王 http://t.co/kMEvAibu
ほぉ〜! |WordPressの the_post() ってそもそも何者? http://t.co/SpJ9ahDJ
WordPressの the_post() ってそもそも何者? | 鉄王
http://t.co/3rhOZvy7
WordPressの the_post() ってそもそも何者? | 鉄王 http://t.co/sB2WSKeK
“WordPressの the_post() ってそもそも何者? | 鉄王” http://t.co/zIhrtAOE
“WordPressの the_post() ってそもそも何者? | 鉄王” http://t.co/zIhrtAOE
“WordPressの the_post() ってそもそも何者? | 鉄王” http://t.co/zIhrtAOE
“WordPressの the_post() ってそもそも何者? | 鉄王” http://t.co/zIhrtAOE
“WordPressの the_post() ってそもそも何者? | 鉄王” http://t.co/zIhrtAOE
なるほど / WordPressの the_post() ってそもそも何者? | 鉄王 http://t.co/EbB58AxQ
WordPressの the_post() ってそもそも何者? | 鉄王 http://t.co/n2SmlBd2
きになる記事
-そもそもworspressのthe_post();って何者?
http://t.co/7fgoXxtr
これはじっくり読まねば。
WordPressの the_post() ってそもそも何者? http://t.co/4ecLMgl8
WordPressの the_post() ってそもそも何者? | 鉄王 http://t.co/sz5iWes2
ピンバック: WordPressの表示フローとLoopとthe_title()〜いろいろ考えたメモ〜 | Webourgeon
テーマ作成時に頭に入れておきたい /
[]ループ文のプログラム的な意味とか
the_post()の振る舞いについて非常に分かりやすい解説記事
"そうです。the_post() にはループ内で値をカウントアップする役割があるのです。"
基礎