ここ最近すっかり放置プレイ気味の本サイトにも、当方のつたないtipsなどをググってお越しくださる方がいらっしゃいます。本当にありがたい限りです。
ということで、2009年1月10日(!)のエントリー『WordPressにて 子ページのタイトルだけでなく本文も一覧で取り出す』にお越しくださった方のリクエストにお応えして、「ホント、こんな情報をご活用くださって感謝です」という思いで続編を公開したいと思います。
リクエストは、出力されたタイトルに当該記事へのパーマリンクを付加したいというもので、コードはこのようになりました……が、ご利用はくれぐれも計画的におねがい申し上げます
1 2 3 4 5 6 7 8 | <?php $page_id = mysql_real_escape_string( $post -> ID ); $array = $wpdb -> get_results( "SELECT ID, post_title, post_content FROM $wpdb->posts WHERE post_parent = '$page_id' AND post_status = 'publish'" ); foreach ( $array as $value ) { echo '<h2><a href="' . get_permalink( $value -> ID ) . '" title="' . sprintf( esc_attr__( 'Permalink to %s', 'twentyten' ), esc_attr( strip_tags( $value -> post_title ) ) ) . '" rel="bookmark">' . esc_attr( strip_tags( $value -> post_title ) ) . '</a></h2>' . "\n"; echo apply_filters( 'the_content', $value -> post_content ); } ?> |
流れは以前のものと変わりませんが、esc_attr や strip_tags も追記して以前のコードよりセキュアなものにしました。
5行目で記載しているように上記のコード例は『TwentyTen』テーマに対応したものとなっているので title 属性をカスタマイズしたい場合には
5 | echo '<h2><a href="' . get_permalink( $value -> ID ) . '" title="' . esc_attr( strip_tags( $value -> post_title ) ) . 'へのパーマリンク" rel="bookmark">' . esc_attr( strip_tags( $value -> post_title ) ) . '</a></h2>' . "\n"; |
といった感じに、また、『My Page Order』プラグインなどで定義したページの並び順で出力したいときは、3行目を
3 | $array = $wpdb -> get_results( "SELECT ID, post_title, post_content, menu_order FROM $wpdb->posts WHERE post_parent = '$page_id' AND post_status = 'publish' ORDER BY menu_order ASC" ); |
というように変えていただければと思います。
[2010.8.31追記]
コメント欄に寄せられた『Custom Field Template』プラグインに対応したコードを追記しました。ページ本文に [cft] ショートコードを挿入した際に親ページでも表示を反映したい、というリクエストをもとにしたコードです。6行目を大幅に変えることになります。
6 7 8 9 10 11 12 | if ( class_exists( 'custom_field_template' ) && preg_match( "/\[cft.*?]/", $value -> post_content ) ) { $content = preg_replace( "/(\[cft.*?)(])/", "$1 post_id=" . $value -> ID . "$2", $value -> post_content ); } else { $content = $value -> post_content; } echo apply_filters( 'the_content', $content ); |
流れを解説しますとこんな感じです。
- 6行目
- 『Custom Field Template』の有無と、ページ本文内の
[cft]ショートコードの有無をチェック。 - 7行目
- 6行目が true の場合の処理。
[cft]ショートコードに子ページのIDを挿入し、変数$contentに代入。 - 10行目
- 6行目が false の場合の処理。ページ本文には手を加えず変数
$contentに代入。 - 12行目
- 変数
$contentの内容を出力。
『Custom Field Template』で定義するショートコードは functions.php と別個に機能しているようなので、追記したようなコードで対応することになります。通常は functions.php にショートコードの処理内容を書いておけば
echo apply_filters( 'the_content', $value -> post_content );
のまま(つまり、当エントリーのいちばん上のコード例)で問題ありません。
子ページタイトルのリンク付き出力、子ページの出力順のフレキシブル化、等、
早速にご対応くださって、誠にありがとうございました。
本文付きで子ページをリスト化する、というコードにはなかなか巡り会えませんでした。
(できる、となっていても自分の場合には、タイトルまでしか出力されなかった、なども。。)
なお、場合によっては、カスタムフィールドの一部も本文として出力したい、というような
要求もでてくるかもしれませんね。
いつか、プラグインにして、ぜひフォーラムに公開してください!ありがとうございました。
少し確かめてみてほしいことが出て来ました。
ページAタイトル
ページA本文
ページBタイトル
ページB本文
で出力されていますが、それに続いて、
ページB本文
ページA本文
が連続して出力されます。昨日試したテーマでは確かよかった筈なのですが、
別のブログですが、今朝、2つのテーマ(Twentyten とThird Style)を切り替えて
試したのですが、やはり同様な結果です。
度々で申し訳ありません。一度みてみてください。お願いします。
m.nakamuraさん
差し支えなければ、当該箇所のソースを示していただけるとありがたいです。ひょっとしたら、何か他のテンプレートタグが邪魔をしているかもしれませんので……
ご返信ありがとうございます。
2度ほど送信しましたが、やはり、タグがサニタイズされてしまうので、
そのまま貼り付けるとコメントが送信できないようです。言葉で言いますと、Twentytenの、
One column, no sidebar Page Template(onecolumn-page.php)の最後のあたりの、
php get_footer();
の直前に挿入しました。よろしくご確認お願いします、。
m.nakamuraさん
同じような条件でやってみたんですが、残念ながらといいますか、こちらでは同じ結果にはならなかったです……『Twenty Ten』『Third Style』ともに、page.php でも onecolumn-page.php でも
ページAタイトル
ページA本文
ページBタイトル
ページB本文
というような感じで出力されました。
フッタウィジェットに何か入ってる、とかはないですよねえ?
蛇足ではありますが
> php get_footer();
> の直前に挿入しました。
この位置だとスタイルシートが利かないので、
< ?php endwhile; ?>の次の行に挿入した方がベターです
> 2度ほど送信しましたが、やはり、タグがサニタイズされてしまうので、
> そのまま貼り付けるとコメントが送信できないようです。
については、当該コードを <code>~</code>で挟んでいただくとコメント欄に投稿できるはずですので、よろしければもう一度お試しいただけないでしょうか。
おはようございます。恐縮です。
まず、ご指摘どおり、スタイルが反映されたのは、とてもよかったです。
「スタイルは後で・・・」と思っていましたが、貴重な情報をいただき、
今後に大変参考になります。
次に、出力内容ですが、フッターに入れていたウィジェットを全て外しましたが、
こちらでは出力内容に変化はありませんでした。
最初お伝えしたように、一昨日、別のPCに構築したXAMPPの中では、うまく行って
いました。そちらでは、Twentytenを試していないので、明日、またやってみて
変化がありましたら、お伝えします。
当方もMT3.3しか使ったことがなく、WPは初心者ですので、どこかで変なことを
やっている可能性もあります。知識もイマイチです。コードタグで囲むことも
忘れておりました・・・・
今はWPでどんなことができるのか、シミュレーションしているようなものなので、
急いでいません。ですので、も少し、自分で調べてみたいと思います。
ありがとうございました。引き続きよろしくお願いします。
m.nakamuraさん
こちらこそ、コードの精度を高めるきっかけになり感謝してます。ありがとうございます。
何か動きがありましたら、ぜひご報告いただけるとうれしいです。同じようなtipsを探している方のために、またいろいろと情報をシェアしていきましょう
別の環境に作っていたデモサイトで、テーマをTwentytenにして確認しました。
昨日のような表示は発生しませんでした。別のテーマ、Arjuna Xでも同様です。
昨日一つわかったことがありました。それは、
・「新しい親ページと、その下に子ページを作っていった場合には、発生しなかった」
ということです。ですので、
・「最初に作成した親ページ・子ページの本文等に何か問題があった」
と考えざるをえません。
ですが、本文等といっても、単純なテキスト(本文とmoreがある)ですので、どこに
問題があるのかはわかりません。
以上の状況ですので、まずはこの状態でコンテンツを作り始めていき、同じような
現象が発生したら情報共有させていただきたいと思います。
以上です。引き続きよろしくお願いします。
先に進んだご相談ですが、以前にちょっと書きましたように、
子ページで投稿した内容の中に、カスタムフィールドを一部表示させました。
これには、Costom Field Templateプラグインを使い、投稿中のページの
カスタムフィールドから設定した項目の一部を、例えばページタイトルの右横
などに表示するために、本文の中に[cft]というショートコードを追記する、
という方法をとりました。
さて、当然のことながら子ページを表示した場合には、ショートコードが効いて
表示してくれますが、親ページから見た場合には、ショートコード以外の本文は
表示されますが、ショートコードまでは表示してくれません。
ここをクリアできないものでしょうか?
m.nakamuraさん
> 本文の中に[cft]というショートコードを追記する、
> という方法をとりました。
とのことですので、すでに functions.php などでショートコードの定義をすませているわけですよね。であれば、本ページ最初のコード例6行目で
echo apply_filters ( 'the_content', $value -> post_content );としてあるので、ページ本文部に埋め込んだショートコードは親ページでも子ページでも反映されるはずですが、ダメでしたか?
ただ、ページタイトル部にショートコードを埋め込んだ場合は、たしかに上記のコード例のままでは反映されないです。5行目の後半をこんな感じに変えることになります。
do_shortcode ( esc_attr ( strip_tags ( $value -> post_title ) ) ) . '' . "\n";
ちなみに上記のコード例では、5行目にてページタイトル部の表示処理を、6行目にてページ本文部の表示処理をしています。
これは、自分のうっかり話なのですが……ページの表示に page.php のテンプレートを選んでいるにもかかわらず onecolumn-page.php を修正していて「あれー、反映されないなー?」なんてこともありました。そのあたりも含めてご確認いただければ、とおもいます
レスありがとうございます。
このプラグインの場合、ショートコードの定義が必要とはなっていないので、
プラグインが有効になっている間は、どこかで定義が有効になっているのだと思います。
function.phpを含め、テンプレートでコードの追記は行っていないので、どのテンプレート
であっても反映されるはずなのですが、うまく行きません。
プラグインの設定画面で、cftで表示する場合のフォーマットを設定していまして、
子ページでは、設定したフォーマット(ここではtableタグ)の中に、商品番号が
ちゃんと表示される(商品番号:123456)のですが、親ページで見ると、フォーマット
は表示されますが、値が表示されない(商品番号:(空白))、という状態です。
デフォルトだと、表示されているページidのカスタムフィールドを見に行くため、
親ページを表示したとき、親ページのidのカスタムフールドを見るために無い、
ということでしょうか?(親ページは、基本的に何も投稿内容はないため)
表示されていて、
ページ投稿欄のショートにおいて、
[cft format=0]としていたのを、
[cft post_id=164 format=0]
などとして、ページidを入れたところ、親ページにも表示されました。
やはり、post_id= を省略すると、デフォルは、当該ページを読む
ようです。(http://wpgogo.com/development/custom-field-template.html)
ただ、投稿時に、そのページのidは、把握しづらいので、投稿の時はデフォルト
でも、親ページを表示した際、一覧で引っ張ってくる子ページのidに読み替えて・・・
というように処理を変更できればよいのですが、いかがでしょうか?
m.nakamuraさん
コメントをくださったのがきっかけで、『Custom Field Template』プラグインを初めて使いました
ありがとうございます。
さて、チカラワザ的な感もなきにしもあらずですが、[cft] ショートコードに post_id を挿入するコードを書いてみました。エントリーに追記しましたのでお試しください。[cft] だけのときも [cft format=0] とフォーマットを指定したときも表示される……ハズです。
teckingさん
これなら、投稿時の作業が楽になり、大変便利になりました。
本当に助かります。
重ね重ねお礼を申し上げます。
ありがとうございました!
別添でお知恵を拝借できないでしょうか?
■製品情報関連のページ群があり、あるページ(例えば、個々の製品ページ)において、タグ(例えば、関連技術)をいくつか指定します。
■製品情報関連のページ群とは、別の、技術関連のページ群があり、これらの各ページのタイトルは、製品情報関連の各ページで指定されるタグと必ず一致するように作るとします。
以上を前提に、
■製品情報関連の各ページの上に、「関連する技術」というブロックを設け、タグを指定すると、これらのタグに一致するタイトルを持った「関連する技術」のページをリストアップする
ということをやりたいのです。ちなみに、関連する技術の各ページには、タイトルと同じタグを持った製品情報関連のページをリストアップして作成するつもりです。こちらの方は、多分WordPressテンプレートタグで可能と想定しています。
参考に、モデルサイトを例示させてもらいます。どうか、お力添え頂けますようお願いいたします。
http://www.adamant-kogyo.com/japanese/index.html
m.nakamuraさん
エントリーの内容からちょっとずれてきたので、はしょったコード例になってしまいますが……デフォルトでは「投稿タグ」が「投稿」でのみ使える(「ページ」では使えない)ということを前提に話を進めると、ある投稿が保持する「投稿タグ」の一覧は
get_the_tagsというテンプレートタグで取得できるので、これを例えば
という具合に展開すると、タグの名前やスラッグを取り出すことができます。
(Codexの get_the_tags の欄もご参照ください)
あとは、取得できた文字列(スラッグ)に
get_bloginfo ( 'url' )で取得できる文字列や
タグを組み合わせれば、ページへのリンクを作ることができるのでは、と思いますがいかがでしょうか。なお、
$tag -> nameや$tag -> slugで取り出せる文字列はそのまま echo するのでなく、いちばん上のコード例のようにesc_attrやstrip_tagsの処理をかませたほうがよいと思います。tecking さま
ヒントを与えていただき、ありがとうございました。
それにしても、「投稿タグ」が「投稿」でのみ使える、ということでは
いままで「ページ」を使ってやっていくつもりだったので、また「投稿」に方向転換
しないとなりません。「ページタグ」まいたいな方法がないかどうか、並行して
調査してみることにします。投稿でもページでも、タクソノミーとかいう機能が
使えるそうなのでですが、これだとどうなんでしょうね?
ページでも、投稿タグを使えるように設定できました。(Simple Tagsプラグイン)
そこで、例えば、投稿だけでなく、ページからも、タグを設定できるようになりました。
これによって、一つのタグ(例えばid=5とか)をある投稿と、あるページに設定してid=5のタグで紐付けできると思われます。
ここまでくると、一昨日いただいたヒントをもとに、何かできると思うのですが。
最初に書いたやりたい事例で言いますと、
製品情報を投稿とし、関連技術を固定ページ年、双方に「技術要素」のタグを付けて紐付けます。
製品の投稿のページには、以下の手順で、関連技術のページの情報を出力しま
す。
1.投稿につけた技術のタグを読み込む。
2.1.で読み込んだ技術から、その同じタグがついている関連技術の固定ページを読み込んで、その固定ページへのリンクを出力する。
一方、関連技術の固定ページには、以下の手順で、その要素技術を使っている製品
の情報を出力します。
1.関連技術ページにつけた要素技術のタグを読み込む。
2.1.で読み込んだ技術から、その同じ要素技術のタグがついている製品の投稿の固定ページを読み込んで、そのリストを出力する。
以上のことをやりたいのですが、前回いただいたヒントに沿って進められますでしょうか?
以上、よろしくお願いします。
度々すみません。素人ながら上記の、
1.投稿につけたタグを読み込む。
2.1.で読み込んだ技術から、その同じタグがついている関連技術の固定ページを読み込んで、その固定ページへのリンクを出力する。
の部分をやってみました。試しに、single.phpにおいて、
<?php
query_posts(‘tag=あるタグ’);
if ( have_posts() ) while ( have_posts() ) :
the_post();
endwhile;
?>
というのをやってみましたが、ページへのリンクは出現しませんでした。
多分、絶対、上のは間違ってますよね?
<?php if ( have_posts() ) : query_posts(‘tag=あるタグ’); ?>
<ul>
<?php while (have_posts()) : the_post(); ?>
<li><a href=”<?php the_permalink() ?>”><?php the_title(); ?></a></li>
<?php endwhile;?>
</ul>
<?php endif; ?>
と修正したら、「投稿」の記事は表示されました。しかし、
‘post_type=page&tag=あるタグ’
として、ページを表示対象にしようとしたら、何も表示されませんでした。
post_type=pageを入れると、入らなくなってしまいます。
ここまで来れば、アドバイスいただいた、get_the_tagsで取得したforeachの中で、
上記のループを回すことができれば、
各投稿の中で、当該投稿に登録したタグのそれぞれにつき、同じタグを持つページのリスト化ができるので、目的とするところに大分近づけてきたと思います。
あと一息ですが、これまで駄文をいっぱい書かせていただいた中で、何かアドバイスいただければ大変幸いです。
m.nakamuraさん
Codexの query_posts のページにあるように、メインのメッセージループ以外で query_posts を使うのは好ましくないとされているので、別解として WP_Query を使ったコードはどうでしょうか。
以上、簡単ですがご参考になれば幸いです。
teckingさま。お忙しいところ、恐縮です。
ある投稿の中で、その投稿に付いたタグと同じタグを持つページへのリンクを得ることが目標です。アドバイスを元に、再構成してみましたが、いかがでしょうか?ちなみにこれだけでは、まだうまく表示されません。引き続きご指導よろしくお願いします。
'page',
'tag' => '$tag'
);
$the_query = new WP_Query ( $args );
if ( $the_query -> have_posts() ) : while ( $the_query -> have_posts() ) : $the_query -> the_post();
?>
<a href="">
うまくコードがコピーされなかったので、を<>に変えて載せます。
<?php
$posttags = get_the_tags();
foreach ( $posttags as $tag ) {
$args = array(
‘post_type’ => ‘page’,
‘tag’ => ‘$tag’
);
$the_query = new WP_Query ( $args );
if ( $the_query -> have_posts() ) : while ( $the_query -> have_posts() ) : $the_query -> the_post();
?>
<a href=”<?php the_permalink() ?>”><?php the_title(); ?></a>
<?php endwhile; else : ?>
<?php endif;} ?>
m.nakamuraさん
このスクリプトのキモは、配列 $args をどう生成するか、ですよね。
まず「投稿」のタグを取得する必要があるので、前半は
という形になるかと思います。get_the_tags 関数でタグの取得を試みて、「投稿」にタグがあった場合のみ4行目以降の処理へ。1行目で定義した配列 $tag_slug にスラッグを格納していきます(6行目)。変数(正確にはクラス)$tag には、タグのIDや名前、スラッグなどの情報が含まれているので、その中からスラッグだけを取り出しているというわけです。
後半はこの流れ。
11行目で、配列 $tag_slug を tag_slug__in の引数として渡しています。
(tag_slug__in はCodexの query_posts のページにて詳解あり)
その後は
とメッセージループを回して完了、という具合です。
タイトルにリンクをつけるなら、15行目に the_permalink() を挿入することになりますね。
m.nakamuraさんが狙ったような結果であればよいのですが。
teckingさま
完璧なコードを書き下していただき、ありがとうございました。またしてもビンゴに至りました。ありがとうございました!
やりたいことを十分お伝えしてなかったにもかかわらず、的確に推測してくれた上で最後まで記述していただいたことにより、お陰様で私としては思い描いていた機能が実現できました。
ここ1ヶ月ほどPHPの解説書に取り組んでいますが、書籍で読んで理解できたつもりになっていても、いざ白いエディターにコードを書くとなると、まったくキーが打てなくなってしまいます。こうして自分の問題を通して、そのコードを理解することで、少しレベルがアップしたような感じです。
とはいえ、まだまだ自分で書けない人だと思うので、引き続きよろしくお願いします。エントリーを汚してしまってすみませんでした。今後、何か訪ねたい場合は、どこにコメントしたらよいでしょうか?
teckingさま
先日はありがとうございました。お蔭様で主目的は達成できましたが、パンくずナビに影響が出ることを発見しました。
Breadcrumb NaviXT というプラグインを導入し、ウィジェットで表示させていたのですが、single.phpテンプレートに14行目~17行目を追加すると、パンくずの最後に、このコードで表示したタグが表示されるようになります。
別のパンくず用プラグインを使い、phpコードを直接書き込めるウィジェットプラグインを使った場合も、ほぼ同様な現象があります。
パンくずナビのロジックと、重なってしまうような部分があるのでしょうか?
m.nakamuraさん
グローバル変数 $post を参照して、表示されているページのタイトルをセットしているのはどれも同じかと思います。『Breadcrumb Nav XT』以外のパンくず系プラグインを使ったことがないので断言はできませんが。
通常の使用であれば $post が書き換わることはまずありませんが、上記コードのような場合、本来書き換わることのない $post を書き換えているので、メッセージループの後で例えばこのような形で $post を書き戻してあげる必要があります。
(グローバル変数 $wp_query, $post については、Codexの「WP_Queryに働きかける」の項をご参照ください)
上記のようなコードを追記することで、その後に生成されるパンくずウィジェットへの影響を回避できるかと思います。
わたしもWordPressの諸先輩方に比べたらまだまだですので、困ったことがあったらまずは、エキスパートが集うWordPress日本語フォーラムをあたられてはいかがでしょうか。「質問ルール」に沿った質問をされれば、何かしら手がかりが掴めるのではないかと思います。
このたびは、ちょっとしたご縁でこのようなやりとりさせていただき、わたしの方もいろいろと勉強することができました。WordPressにほれ込んでいる一人として、m.nakamuraさんのようにWPユーザがまた増えたことをうれしく思います
tecking さま
ありがとうございました!
またまた、たちどころに問題は解消されました。いずれのBreadcrumbsも
同様に正常になりました。
すごいなぁ。ホントに・・・自分はとてもこんなにプログラムを理解できないかも。
引き続き、勉強します。恐る恐る、フォーラムに参加してみます。
ありがとうございました。また、よろしくお願いします。