WordCamp Osaka 2012に参加してきました

2012/11/03に大阪の天満研修センターで開催されたWordCamp Osaka 2012に行ってきました。
WordCampは去年のWordCamp Kobe 2011以来の2回目。機会があればTokyoも行ってみたいですが。

前乗り〜前夜祭

WordCamp Osaka 2012本編が朝から開始だったので今回は大阪に前乗りすることに。
2日朝9時頃高松を発って13時頃には大阪へ。いつも通りポケモンセンターオーサカへ行ってピカチュウにお布施をした後、梅田から15分程度離れた宿へチェックイン。

せっかくの大阪なのでコワーキングスペース訪問しておきましょうということで16時に@styledesignさんとJUSO Coworkingさんへ。
付近の方は翌日のWordCampの準備の為に行かれていたのかほぼ貸切状態でいつも通りの2人会になってしまいましたがとてもいい雰囲気のコワーキングスペースでした。
大阪方面は所要でちょこちょこ行くので機会があればまた利用させて頂きたいですね。

JUSO Coworking

夜は@luchino__さんのご好意で前夜祭に参加。
WordCamp Osakaスタッフさんや各地のWPerさんが多数いらっしゃってて人見知りの私としては緊張の場でしたが、各WordBenchイベントに参加した際お会いした事がある方もいらっしゃったので普段よりはコミュニケーションがとれたかな、と。
Twenty Twelveについて解説して頂いたり、良さそうなプラグインを紹介して頂いたりと私個人としては本編、懇親会よりも前夜祭が一番WordPressの話題で盛り上がったような気が・・・。お相手してくださった皆さんありがとうございました。

WordCamp Osaka前夜祭

WordCamp Osaka 2012

そして本編へ。
私が聴講したのは以下のセッション。

  • WordPressのいまと、これから
  • 地域勉強会コミュニティ「WordBench」に行ってみよう
  • お昼休憩でセッション聞けず
  • 闇WordCamp
  • 基調講演:WordPress 対談 〜大阪・日本の WordPressを語る!〜
  • 登壇者と話そう!
  • ライトニングトーク

個別の感想は控えるとして、良かった点としては全体を通してスタッフさんの誘導なり仕切りがスムーズだったという点。
参加者900名強だったと記憶していますが私が感じた限り特に混乱も起きていなかったようですし、会場内の移動もスムーズに行えました。
スタッフの皆さんありがとうございました。

こうだったら良かったなという点としては、参加者自身が参加できるセッションがもう少しあれば良かったかなと。今回聴講した中では「登壇者と話そう!」が唯一そうだったのですが「WordBench〜」「闇WordCamp」もそういった内容かなと想定し参加したのですがカンファレンス形式だったのでちょっと残念でした。(内容自体は勉強になりましたし、面白かったのですが)
「登壇者と話そう!」では大曲さんのプログラマ向けのグループに参加していたのですが最初大曲さん対10数名で質問者以外は解説を聞くだけになってしまっていたので、途中で宮内さん、中本さんが参加された段階で3グループに別れてたら皆発言できてたかなと感じました。

ちなみにライトニングトークの「WordPressあるある」にあったカニ、うどん、カレー全て参加してるのは私だけです!!

うどんわぷーシール配布させて頂きました。

入江さんによる「WordPressのいまと、これから」

Automatticブースにて直子さんとピカチュウ2ショット

プライム・ストラテジーさんブース。
教科書わぷーシール分けていただいたのでWordBench香川で配布します。

基調講演:WordPress 対談 〜大阪・日本の WordPressを語る!〜

登壇者と話そう!のお三方

懇親会

というわけで本編も終わって懇親会へ。
開場まで時間があったので道頓堀付近をうろちょろしたり心斎橋のアップルストアへお使いに行ったり。

懇親会の雰囲気は前回のWordCamp Kobe 2011の時に分かっていましたがやっぱり慣れませんね。もうちょっと社交性を身に付けれるようになりたいです・・・
あまり話し掛ける事が出来ませんでしたがお話、名刺交換して下さった皆さんありがとうございます。

WordCamp恒例のケーキ

あっちっち本舗さんの出張たこ焼き屋台
本場のたこ焼き旨い!!

懇親会はこんな雰囲気でしたー

直子さんと一緒に写真撮って貰いました。ありがとうございます!

最後に

まず運営スタッフの皆さんありがとうございました。そしてお疲れ様でした。
当日の運営もそうですが、開催までの段取り等、twitterのTLでそれらしきツイートを拝見して大変さが伝わって来ました。
前夜祭で香川はやらないの?みたいな話を振られましたが(最近WordPressイベントに行くとよく言われますねw)自分では無理だな、というのが正直なところです。
イベントに関して思うところは各々でしょうし、運営側ともなればこうしておけばといったことも多々あるでしょうけど、それでもイベントをやると決め、それをやり遂げた事はとても素晴らしい事だと思いました。

改めて運営スタッフ、参加者の皆さんお疲れ様でした。

「第6回WordPressお茶会 WordBench香川」を開催しました

2012/10/06(土)[13:00~18:00]にデザインラボラトリー蒼様をお借りして「第6回WordPressお茶会 WordBench香川」を開催しました。

今回は新規2名を含む計8名の方にご参加での開催となりました。
内容としてはいつも通りノーテーマでのだらだら喋るだけ、土井によるWordPressテーマ構築ハンズオン、ライトニングトークの3本。

ハンズオンの内容としては『WordPress 3.x (速習デザイン)』のCafe Miraggioテーマを参考にトップページに通常の投稿ループに加えカスタム投稿タイプのループを出力、及びカスタム投稿タイプではカスタムフィールドを用いて追加の要素を表示させよう、という内容を考えていました。
Cafe Miraggioテーマの使用をご快諾くださった@jim_0912さんありがとうございました。


photo by: style-design

参加者さんにとって初めてのテーマだったので全体的なテーマの構造について、次いでheader.phpの内容を一通り説明して、という流れになったのですがCafe Miraggioテーマではheader.php内に独自関数を使用していたのでfunctions.phpへ飛んでその説明、更にはその中のWordPress関数の説明のためにCodexに飛んでその説明と、脱線しまくりになってしまい肝心のループまで辿りつけなかったので反省です。
ループメインのハンズオンの場合header.php等は「こういうものですよ」という前提で進めないと駄目ですね。
来月11/03に開催されるWordCamp Osaka 2012に各WordBenchの方もたくさんいらっしゃると思うのでハンズオン含めWordBench運営について意見を頂戴したいですね。

トーク班は今回は技術寄りの方が多かったようでAndroidやらRuby、HTML5の話題で盛り上がっていたようです。
その場でも話題にしましたが、ATNDで参加登録された方が技術者の方の場合、私だと対応できないので「相手できるよ!」って方がいらっしゃったら是非参加してい頂けるとありがたいです。

LTは@_nobinobiruさんによる「jQuery+HTMLで作ったフロントエンドにBackboneを導入」、@styledesignさんによる「逆に考えるんだ!セミナーイベント規模を小さく小さくして個人レッスンに近いかたちにするといいよ」の2本立て。

@_nobinobiruさんのLTはBackbone.jsの説明から入って実演、ソース解説という流れでしたが私が理解できたのはほんの一部ですのでこちらで説明しきれませんので興味のある方は@_nobinobiruへリプライを。
感想としては「知られてないだけでこんなすごい人がまだまだいるんだ、しかも若い!」の一言に尽きます。

@styledesignさんのLTは「逆に考えるんだ!セミナーイベント規模を小さく小さくして個人レッスンに近いかたちにするといいよ | スタイルデザインWeblog」の内容をざっくりと。
イベント・勉強会のスタイルについてですがこちらはとても共感。私がこうしていきたいって考えているWordBench香川コミュニティのあり方がまさに説明されているなと。

というわけでハンズオンはいつも通りグダグダになってしまい反省点も多々ありますが、全体的には楽しく開催できたし参加者のかたにも満足して頂けたのではないかなと。

次回「第7回WordPressお茶会 WordBench香川」は12月中旬くらいに開催予定(未定)です。
が、その前にWordPressのお祭りWordCampが大阪で開催されますので、まずはそちらを楽しみたいですね!!

WordCamp Osaka 2012は2012/11/03(土)天満研修センターにて開催。

WordCamp Osaka 2012

AjaxでWordPressのコンテンツを遷移せず表示させる

WordPressのコンテンツをtwitterやgoogle画像検索のようにあらかじめ一定数のコンテンツを表示させておき「もっと見る」リンクをクリックで画面遷移無くコンテンツを出力させたいと思います。

INDEX

  1. 仕様・デモ
  2. WordPressでAjaxを使う

    1. /wp-admin/admin-ajax.phpを使う
    2. /wp-admin/admin-ajax.phpを使ったデモ
  3. 表示用の固定ページ作成
  4. functions.php周り

    1. JavaScript登録
    2. 全投稿数を取得しクッキーに保存させる
    3. 「もっと見る」クリック時のAjax処理登録
  5. 課題等
  6. 参考サイト

仕様・デモ

いくつか課題はありますが、とりあえずの仕様としては以下の通り。

  • 投稿のタイトル及びリンクをあらかじめ一定数表示(今回は10件)
  • 「もっと見る」をクリックする度にAjaxでコンテンツを取得し10件ずつ追加
  • 固定ページ「AjaxでWordPressのコンテンツを遷移無く表示サンプル(page-wp-content-ajax-viewer.php)」を作成しそこに出力
  • すべてのコンテンツを表示し終えたら「もっと見る」リンクは無効化にする
  • テーマはTwenty Elevenをベースに

実際のデモは以下よりご覧ください。
AjaxでWordPressのコンテンツを遷移無く表示デモ

WordPressでAjaxを扱う

実際の処理部分の説明の前にWordPressでAjaxを扱う方法を。

/wp-admin/admin-ajax.phpを使う

AJAX in Plugins – WordPress Codex 日本語版が本家マニュアルだけど複雑で理解できなかったのでgoogle先生に頼りました。
分かりやすかったのは次のサイト。
Wp Ajax – WordPress Hook to Handle Ajax Request — W4dev.com
仕組みとしては次のようなイメージ(自己解釈)。

  • JavaScriptで/wp-admin/admin-ajax.phpへリスエストを送信することで任意のPHP関数を呼び出し、そこから送り返された情報をもとにJavaScriptで結果を出力する。
  • 任意のPHP関数はアクションフック「wp_ajax_アクション名」「wp_ajax_nopriv_アクション名」で呼び出すことができ、これらアクションフックを実行するには/wp-admin/admin-ajax.phpリクエスト時のactionパラメータに「アクション名」を渡しおく。
    「wp_ajax_アクション名」「wp_ajax_nopriv_アクション名」はログインユーザか否かで、公開部分でAjax処理を行いたい場合はともにフックする必要がある。

    01
    02
    03
    04
    05
    06
    add_action( 'wp_ajax_my_func', 'my_func' );
    add_action( 'wp_ajax_nopriv_my_func', 'my_func' );
     
    function my_func() {
        // JavaScriptに値を返す処理
    }
  • my_funcにはJavaScript側に渡す情報を出力する処理を。

/wp-admin/admin-ajax.phpを使ったデモ

/wp-admin/admin-ajax.phpを使ってAjax処理を行うデモ

ソースは以下の通り。

page-wp-ajax-demo.php

01
02
03
04
05
06
// ヘッダとか省略
<div class="entry-content">
    <a href="#" id="show-json">JSON出力</a>
    <div id="json-data"></div>
</div><!-- .entry-content -->
// フッタとか省略

ヘッダ、フッタ領域は省略しています。
jQueryのclick()イベント用のアンカーとJSONデータ出力用のdivを用意。

functions.php

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// JavaScript登録
add_action( 'wp_enqueue_scripts', 'sh_add_scripts' );
 
function sh_add_scripts() {
    if ( is_page( 'wp-ajax-demo' ) ) {
        wp_enqueue_script( 'jquery' );
    }
}
 
// admin-ajax.phpへリクエストを送信し返ってきた情報をもとにページ情報を出力
add_action( 'wp_head', 'sh_show_json' );
 
function sh_show_json() {
    if ( is_page( 'wp-ajax-demo' ) ) {
        ?>
        <script>
            //<![CDATA[
            ajaxurl = '<?php echo admin_url( 'admin-ajax.php' ); ?>';
            jQuery(function($){
                $('#show-json').one('click', function(){
                    jQuery.ajax({
                        type: 'POST',
                        url: ajaxurl,
                        data: {
                            "action": "sh_get_json"
                        },
                        success: function(data){
                            var json_str = JSON.stringify(data);
                            $('#json-data').append(json_str);
                        },
                        error: function(){
                            alert('error');
                        }
                    });
                    $(this).css({
                        'pointerEvents': 'none',
                        'color': '#ccc'
                    });
                    return false;
                });
                return false;
            });
            //]]>
        </script>
        <?php
    } // endif
}
 
// json出力
add_action( 'wp_ajax_sh_get_json', 'sh_get_json' );
add_action( 'wp_ajax_nopriv_sh_get_json', 'sh_get_json' );
 
function sh_get_json() {
    $charset = get_bloginfo( 'charset' );
    $array = array( 'foo' => 'bar', 'hoge' => 'fuga' );
    $json = json_encode( $array );
    nocache_headers();
    header( "Content-Type: application/json; charset=$charset" );
    echo $json;
    die();
}

jQuery.ajax()を使用するので#01~08でjQueryの登録。
デモページスラッグ名がwp-ajax-demoなのでis_page( ‘wp-ajax-demo’ )でデモページのみ読み込まれるように。

#10~47でデモページにJavaScriptを出力。処理内容は以下の通り。

  • jQuery.ajax()のリクエスト先URLを設定(#18)
  • 「JSON出力」アンカー(#show-json)クリックイベント(#20)
  • jQuery.ajax()実行。(#21~)
    urlは”/wp-admin/wp-ajax.php”、dataキー(サーバに送信するデータ)のactionパラメータとして”sh_get_json”を渡す。後述のsh_get_json()が実行されJSONオブジェクトを返す。
    通信成功時には渡されたJSONオブジェクトをJSON文字列に変換し出力。(#27~30)

#49~61でJSON出力処理。

  • /wp-admin/admin-ajax.php?action=sh_get_jsonへのリクエストでアクションフック”wp_ajax_sh_get_json”、”wp_ajax_nopriv_sh_get_json”がフックされ、sh_get_json()が実行される。(#51,52)
  • sh_get_json()では適当な配列$arrayを作成し、json_encode()で配列をJSON形式にして出力。
  • JSONを出力したままだとエラーが発生するのでdie()でプログラムを終了させる。(#60)
  • 出力されたJSONが先のsh_show_json()のjQuery.ajax()のsuccess時の引数”data”として渡され適宜処理される。

というわけで/wp-admin/admin-ajax.phpについて一応の理解はできたところで本題に戻って実際の処理を行なっていきます。

表示用の固定ページ作成

まず固定ページ「AjaxでWordPressのコンテンツを遷移無く表示サンプル(page-wp-content-ajax-viewer.php)」を作成して投稿の最新10件を表示します。

page-wp-content-ajax-viewer.php

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?php
/**
 * AjaxでWordPressのコンテンツを遷移無く表示デモ
 *
 * @package WordPress
 * @subpackage Twenty_Eleven
 * @since Twenty Eleven 1.0
 */
get_header();
?>
<div id="primary">
    <div id="content" role="main">
        <article id="wp-content-ajax-viewer" <?php post_class(); ?>>
            <header class="entry-header">
                <h1 class="entry-title"><?php the_title(); ?></h1>
            </header><!-- .entry-header -->
            <div class="entry-content">
                <?php
                $args = array(
                    'posts_per_page' => 5
                );
                $my_posts = get_posts( $args );
                if ( $my_posts ):
                    $output = '';
                    $output .= '<ul id="content-list">';
                    foreach ( $my_posts as $post ):
                        $output .= '<li><a href="' . get_permalink() . '">' . get_the_title() . '</a></li>';
                    endforeach;
                    $output .= '</ul>';
                    echo $output;
                endif;
                ?>
                <a id="show-more" href="#">もっと見る</a>
            </div><!-- .entry-content -->
        </article>
    </div><!-- #content -->
</div><!-- #primary -->
 
<?php get_footer(); ?>
    

get_posts()で最新10件を取得し、リスト形式でタイトル・パーマリンクを出力しています。

functions.php周り

JavaScript登録

jQuery.ajax()を使用するのでjQueryを、全投稿数保持の為にjquery.cookieプラグインを利用するので登録しておきます。

functions.php

01
02
03
04
05
06
07
08
09
// JavaScript登録
add_action( 'wp_enqueue_scripts', 'sh_add_scripts' );
 
function sh_add_scripts() {
    if ( is_page( 'wp-content-ajax-viewer' ) ) {
        wp_enqueue_script( 'jquery' );
        wp_enqueue_script( 'jquery-cookie', get_template_directory_uri() . '/js/jquery.cookie.js', array( 'jquery' ), true );
    }
}

全投稿数を取得しクッキーに保存させる

投稿を全て表示し終えたら「もっと見る」アンカーを無効化する、を実現するために全投稿の件数が必要になります。
ページ読み込み時に全投稿数をカウントしてクッキーに保存しておきます。

2012/10/17修正
wp_headにフックさせるとhtmlを出力した後setcookie()が実行され”Warning: Cannot modify header information – headers already sent by”が発生するのでinitにフックするよう修正しています。
PHP: setcookie – Manual

2012/10/17更に修正
initにフックさせるとsh_get_query_count()関数内のis_page()が効かないのでwpフックに修正。

functions.php

01
02
03
04
05
06
07
08
09
10
11
// 全投稿数をカウントしクッキーに保存
add_action( 'wp', 'sh_get_query_count' );
 
function sh_get_query_count() {
    if ( is_page( 'wp-content-ajax-viewer' ) ) {
        $args = array( 'posts_per_page' => -1 );
        $my_posts = get_posts( $args );
        $query_count = count( $my_posts );
        setcookie( 'count', $query_count, time() + 3600 );
    }
}

「もっと見る」クリック時のajax処理登録

functions.php

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// admin-ajax.phpへリクエストを送信し返ってきた情報をもとにページ情報を出力
add_action( 'wp_head', 'sh_add_ajax_script' );
 
function sh_add_ajax_script() {
    if ( is_page( 'wp-content-ajax-viewer' ) ) {
        ?>
        <script>
            //<![CDATA[
            ajaxurl = '<?php echo admin_url( 'admin-ajax.php' ); ?>';
            jQuery(function($){
                $('#show-more').click(function(){
                    var paged = $('#content-list li').length;
                    jQuery.ajax({
                        type: 'POST',
                        url: ajaxurl,
                        data: {
                            "action": "sh_show_more",
                            "paged": paged
                        },
                        success: function(data){
                            var html = generateHtml(data);
                            var target = $('#content-list');
                            $(target).append(html);
                            if ( $('#content-list li').length == $.cookie('count')) {
                                $('#show-more').css({
                                    'pointerEvents': 'none',
                                    'color': '#ccc'
                                });
                            }
                        },
                        error: function(){
                            alert('error');
                        }
                    });
                    return false;
                });
                function generateHtml(data){
                    var dataLength = data.length;
                    var li = [];
                    for ( i = 0; i < dataLength; i++ ){
                        li.push('<li><a href="' + data[i].url + '">' + data[i].title + '</a></li>');
                    }
                    li = li.join("");
                    return li;
                }
            })
            //]]>
        </script>
        <?php
    } // endif
}
 
// json出力
add_action( 'wp_ajax_sh_show_more', 'sh_show_more' );
add_action( 'wp_ajax_nopriv_sh_show_more', 'sh_show_more' );
 
function sh_show_more() {
    global $post;
    $charset = get_bloginfo( 'charset' );
    $paged = $_POST['paged'];
    $json = array( );
    $args = array(
        'posts_per_page' => 10,
        'offset' => $paged
    );
 
    $my_posts = get_posts( $args );
    foreach ( $my_posts as $key => $post ) :
        $json[$key]['title'] = get_the_title();
        $json[$key]['url'] = get_permalink();
    endforeach;
     
    $json = json_encode( $json );
    nocache_headers();
    header( "Content-Type: application/json; charset=$charset" );
    echo $json;
    die();
}

基本は/wp-admin/admin-ajax.phpを使ったデモと同じなのでそちらを参照。

大まかな流れとしては以下の通り。

  1. wp_headアクションフックでsh_add_ajax_script()を実行し(#02)、「AjaxでWordPressのコンテンツを遷移無く表示デモ」ページのみJavaScriptを出力(#05)
  2. 「もっと見る」アンカー(#show-more)クリックイベント(#11)
  3. 現在表示されている投稿件数を取得。(#12)
  4. jQuery.ajax()実行。(#13~)
    今回はdataキー(サーバに送信するデータ)にactionパラメータ他にpagedパラメータを登録。pagedパラメータは#12で取得した現在表示されている投稿件数の値。
  5. /wp-admin/admin-ajax.php?action=sh_show_moreへのリクエストでアクションフック”wp_ajax_sh_show_more”、”wp_ajax_nopriv_sh_show_more”がフックされ、sh_show_more()が実行される。(#54,55)
  6. PHP関数側で$pagedにjQuery.ajax()より送信されたpagedの値を代入。(#60)
  7. get_posts()用のパラメータを設定。posts_per_page(表示件数)は10件。offset(取得開始位置)$pagedの値を。
    他パラメータは今回はデフォルトで。画像で同様の処理を行いたいなら’post_type’ => ‘attachment’とかを指定。
  8. get_posts()で投稿を取得してきて(#67)、foreachで配列$jsonにタイトルとパーマリンクを代入。(#68~71)
  9. 先のデモ同様JSONを出力してdie()でプログラムを終了させる。(#73~77)
  10. jQuery.ajax()にJSONオブジェクトが返されsuccess時の処理実行。(#20~)
    出力するhtmlを生成し(#21及び#37~45)、指定した要素へ出力。(#22,23)
  11. もし投稿件数がcookieに保存されている全投稿数と同じになれば「もっと見る」アンカー無効化処理。(#24~29)

ちなみにjQuery.ajax()でsuccess時に返ってくるJSONオブジェクトは以下の様な形式。(JSON文字列化及び整形済み)

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
[
    {
        "title": "Mac OS X Lion環境NetBeans IDEにプログラミング用フォントRicty導入",
    },
    {
        "title": "WordCrab Fukui 2012に参加してきました",
    },
    {
        "title": "Windows7でSCSS+Compass(導入編)",
    },
    {
        "title": "Retinaディスプレイ時に読み込む画像を切り替えるjQueryその2",
    },
    {
        "title": "Retinaディスプレイ時に読み込む画像を切り替えるjQuery",
    },
    {
        "title": "第1回WordPressお茶会@WordBench香川を開催しました",
    },
    {
        "title": "第1回WordPressお茶会 &#8211; WordBench香川 &#8211; WordPressのインストール",
    },
    {
        "title": "第1回WordPressお茶会 &#8211; WordBench香川 &#8211; PHP環境設定",
    },
    {
        "title": "第1回WordPressお茶会 &#8211; WordBench香川 &#8211; MAMPの環境設定(外部からのアクセス制限設定)",
    },
    {
        "title": "第1回WordPressお茶会 &#8211; WordBench香川 &#8211; XAMPPの環境設定(ドキュメントルートの確認)",
    }
]

課題等

以上でタイトル通りの処理は実現できましたがいくつか課題が。

  • ソースが全体的に冗長的。(get_posts()の条件を変更したい場合、例えば出力件数等を変更したい場合、page-wp-content-ajax-viewer.phpとfunctions.phpともに変更する必要がある)
    Class化とかである程度対応出来そう?
  • 拡張性が無い。(出力内容を変更したい場合ソースを結構変更する必要があるので面倒)
    これもClass化で対応出来そう?
  • セキュリティ的にどうか。(まだそこまで検証出来てません)
  • プラグイン化して、WP-PageNaviプラグインみたいにindex.phpやarchive.phpの所定の箇所に関数を書くと、「もっと読む」クリックで投稿が出力されたら面白いかなと。(既にあるか?)

参考サイト

以下サイトを参考にさせて頂きました。