投稿日:

WordPress の the_title() は出力されるが、the_content() が出力されないことがある理由


@Webourgeon_com さんのブログに次の記事がアップされました。

これが一体なぜだろう?という話ですね。
実はちょうど僕も近いところを調べていたところだったので興味を持ちました。以下は @Webourgeon_com さんの記事を受けての検証記事ですので、できれば上の記事を読んでいただいてからこちらも読んで頂ける方が分かり易いかも知れません(この記事だけ読むと唐突すぎるかも、です)。

§ 検証

the_title も the_content も、どちらも内部的には別の関数、get_the_title、get_the_content をコールしています。この2つの関数いずれも、関数内の最初で次のようにコールしています。

get_post() を引数無しで呼び出すと、その時点で $GLOBALS[‘post’] に格納されている WP_Post データを取得しようと試みます。ここでは、get_the_title、get_the_content いずれの関数でも、ループの内外に関わらず、データは取得できていました(ちなみに、僕が興味を持って調べていたのはこのあたり)。

次に、get_the_title() のソースを眺めてみます。

特に気になる点はありません。各種フィルターが影響してなければ、ポイントは 105 行目になると思います。

では次は get_the_content() を見てみます。

よく見るととても面白いです。get_the_content() が返すであろうデータ $post->post_content は、ここでは一度しか利用されておらず、またはそれは出力ではなく、noteaser 記法の有無の判定だけに利用されていることです。

では、get_the_content() は何を返しているのか?
コードを見ると、それはグローバル変数「$pages」のようです。

試しに、ループなどで the_post() を呼び出しする前に、the_content() をコールしてみると、$pages の内容は設定されておらず、結果として the_content() 関数は何も出力しません。

では、$pages の内容はどこで設定されているのかというと、結論から言うと、setup_postdata() という関数の中です。ループ等で the_post() をコールする時も、その the_post() の中で setup_postdata() はコールされます。

それでは、setup_postdata() の内容を確認してみます。

たしかに、3640 行目以降で $post->post_content をベースにして、$pages の内容はここで作られていますね。

§ まとめ

「ループ外で、the_title() をコールしたときにはタイトルが出力されるが、the_content() は出力されないのは何故だろう?」

答えは、「the_content() が実際に出力するものはページネーションの為に準備された $pages というグローバル変数の内容で、またその $pages は、setup_postdata() 関数がコールされる以前にはまだ初期化されていないため」となります。

「タイトル表示できるなら、投稿内容も表示できるだろう」という感じではありますが、実際の仕組みはこんな風になっていました。

§ 考察

とはいえ、本稿の発端となる @Webourgeon_com さんのように疑問に感じる面もありそうな実装仕様ではあります。それについて少しだけ考えをまとめてみました。

まず、データを取ってくることと、それを加工することはプログラミングでは一般に別のフェーズです。またデータの加工は、それを利用するにあたって可能な限り実際に利用する場所に近いところで行うことが望ましいです。これらの事から、取得したデータを利用する局面…この記事の文脈では「the_post() をコールするその時」に、出力の為にデータをセットアップする、というのは利に適った実装仕様だと僕は思いましたが、どうでしょうか。

なお、この問題は本質的に WordPress のループとは関連がありません。ループ内でよく利用される関数が利用するデータが、単にまだ準備されていなかっただけで、それらのデータの準備の為に setup_postdata() という関数が存在している、ということですね。ですので、while などでループさせて the_post() を呼び出さなくても、単に the_post() をコールしても良いですし、setup_post( get_post() ) としても大丈夫です。 

 

 

 

コメントを残す