WordPressとFlashの連携(ページ分けをしたい)
- 2009 年 4月 2 日
前回の内容は、WordPressを使わない場合に置き換えるなら、ひとつのxmlファイルを使う想定になると思います。xmlの子ノードに記載される内容が一覧等に使う軽い内容なら、1000件あたって容量も処理時間も問題ないと思いますが、諸般の事情で複数ページに分けたい時もあると思います…。僕にはありました。今回はページ分けについて試した時の記録です。
ページの分け方もケース次第なので条件を設定。条件は全エントリーを対象にカテゴリーやタグなどで絞りこんで、1ページあたり5つのエントリーにしたxmlを生成。絞りこんだエントリー数分のページをxmlで出力するって条件でやってみました。
まずページを分ける最低限必要なことを考えて、必要な要素の取得方法を得る為にWordPressのタグリファレンスやGoogleと格闘すること小一時間…。やっとの思いで以下の手法を得る。
公開されている全エントリー数の取得
$count_posts = wp_count_posts();
$published_posts = $count_posts->publish;
参考:
Function Reference/wp count posts « WordPress Codex
絞りこんだ後のエントリー数の取得
$numposts = $wp_query->found_posts;
参考:
「○○件中 ○件を表示中」現在の位置、ページ数表示
検索結果の件数を表示【WordPressカスタマイズメモ】
現在表示しているページ番号を取得
$paged = get_query_var(‘paged’);
参考:
WordPress › フォーラム » ページでページングを利用したい
ループ内のクエリを変更(エントリー取得の仕方を条件指定)
query_posts(‘arguments’)
WordPressループの前にこのテンプレートタグを設置して取得方法を指定できる。
渡す引数の例:
1ページに表示するエントリー数を指定 = posts_per_page
表示するページを指定 = paged
参考:
テンプレートタグ/query posts – WordPress Codex 日本語版
この辺がわかっていればページ分けは出来そう。
で、これらを使って、Flashでページを切り替えて表示するにあたり、FlashからWPにリクエストするURLにはクエリを設定してWordPress取得して処理する。
その結果出力されたxmlは、次回Flashからリクエストするのに必要な情報を付与する。
ってことが必要。
これを踏まえて以下のテンプレートを作ってみました。
<?php /* Template Name:cms */ ?> <?php header( "Content-Type: text/xml; charset=" . get_option( 'blog_charset' ) ); echo '<?xml version="1.0" encoding="' . get_option( 'blog_charset' ) . '"?' . '>'; ?> <?php //1ページに表示する投稿数を指定 $posts_per_page = 5; //現在のページ $paged = get_query_var('paged'); $paged = ( $paged ) ? $paged : 1; ?> <?php query_posts("posts_per_page=$posts_per_page&paged=$paged"); ?> <?php $numposts = $wp_query->found_posts; ?> <root numposts="<?php echo $numposts ?>" posts_per_page="<?php echo $posts_per_page ?>" paged="<?php echo $paged ?>"> <?php if (have_posts()) : ?> <?php while (have_posts()) : the_post(); ?> <entry release="<?php echo c2c_get_custom("Release"); ?>" flv="<?php echo c2c_get_custom("FlV"); ?>" image="<?php echo c2c_get_custom("Image"); ?>" title="<?php echo c2c_get_custom("Title"); ?>" song="<?php echo c2c_get_custom("Song"); ?>" artist="<?php echo c2c_get_custom("Artist"); ?>" > <?php echo c2c_get_custom("Ditail"); ?> </entry> <?php endwhile; ?> <?php else : endif; ?> </root> |
実際にテスト版を作ってみた。(たまにいじっているので今後現状のまま公開し続けれるかわからないです。)上のテンプレート使っているXMLを出力する固定ページが以下です。
で、通常のページでは確認用にメタ情報を本文に表示しています。
通常のページ
※サンプルで使っている映像素材は、無料のVJ素材 映像素材 1 gdm.NETさんの素材をお借りしています。
cmsページのxmlを参照して動作しているSWFがこちら。
SWFのページ
Flashでxmlの処理しているところはこんな感じ。Progressionは非同期処理を書くのにも秀逸だね。
package index{ import flash.net.URLRequest; import flash.xml.XMLNode; import index.btn.BtnNext; import index.btn.BtnPrev; import index.loading.Loading; import index.player.Player; import index.thumb.*; import jp.nium.utils.MathUtil; import jp.progression.*; import jp.progression.casts.*; import jp.progression.commands.*; import jp.progression.events.*; import jp.progression.loader.*; import jp.progression.scenes.*; public class IndexScene extends SceneObject{ public function IndexScene(){ this.title = "sample"; this.onInit = this.onInitHandler; this.loading = new Loading( { x:CastDocument.centerX, y:CastDocument.centerY } ); this.thunbContainer = new ThumbContainer(); this.btnPrev = new BtnPrev( { x:35, y:125 } ); this.btnNext = new BtnNext( { x:465, y:125 } ); } public var loading:Loading; public var player:Player; public var btnPrev:BtnPrev; public var btnNext:BtnNext; public var thunbContainer:ThumbContainer; public var debugField:CastTextField; protected function onInitHandler():void{ this.request( this.sceneInfo.query.toString() ).execute(); } //WordPressにxmlをリクエストして表示するコマンドリスト public function request( q:String ):SerialList{ //qにはクエリの文字列 var comm:SerialList = new SerialList(); //このコマンドリスト comm.addCommand( new RemoveChild( progression.container, thunbContainer ), new RemoveChild( progression.container, btnNext ), new RemoveChild( progression.container, btnPrev ), new AddChild( progression.container, loading ), new LoadURL( new URLRequest( "http://sample.nipx.jp/wordpress/?page_id=3&" + q ) ), new Func( function():void{ var doc:XML = new XML(this.latestData); //直前のコマンドからデータを取得 var numposts:Number = Number( doc.@numposts ); //このクエリで絞り込んだ場合の全エントリー数 var posts_per_page:Number = Number( doc.@posts_per_page ); //1ページに表示するエントリー数 var paged:Number = Number( doc.@paged ); //現在表示中のページ番号(1=最初) paged = ( !paged || paged < 1 ) ? 1 : paged; //空の時、1より小さい時は1 var max:Number = Math.ceil( numposts / posts_per_page ); //全エントリー数/1ページに表示するエントリー数 = 最大ページ数 btnNext.sceneId = new SceneId( "/index", { paged:paged+1 } ); //次へボタンに新しいクエリを設定 btnPrev.sceneId = new SceneId( "/index", { paged:paged-1 } ); //戻るボタンに新しいクエリを設定 var margin:Number = 5; //サムネイルを並べる時のマージン //サムネイルのコンテナを生成(画面中央に表示) thunbContainer = new ThumbContainer( { x:CastDocument.centerX - ( (Thumb.WIDTH * posts_per_page) + margin * (posts_per_page-1) ) / 2, //サムネイルの幅*ページに表示する数、マージン*ページに表示する数-1 y:CastDocument.centerY - Thumb.HEIGHT/2 //サムネイルの高さ/2上に移動 }); //xmlからサムネイルを生成 var parallelList:ParallelList = new ParallelList(); //外部イメージを表示する為コマンド var serialList:SerialList = new SerialList(); //xmlの値を格納し外部イメージを読み込むコマンド //エントリー数繰り返し for( var i:uint=0; i<doc.entry.length(); i++ ){ //ノードを格納しサムネイルのクリップを生成 var node:XMLNode = doc.entry[i]; var thumb:Thumb = new Thumb( { node:node, x:( Thumb.WIDTH + margin ) * i } ); //サムネイルへの参照 var image:ThumbImage = thumb.image; //サイネイルの画像への参照 image.y = Thumb.HEIGHT * ( MathUtil.even(i) ? 1 : -1 ); //サムネイルの画像は交互に上下位置をずらして配置 serialList.addCommand( new AddChild( thunbContainer, thumb ) ); //サムネイルを表示リストに追加するコマンドを設定 parallelList.addCommand( new AddChild( thumb, image, { delay:i*150 } ) ); //サムネイルの画像をサムネイルに追加するコマンドを設定 } //コマンドリストに設定 this.parent.addCommand( serialList, //サムネイル画像を順番に読み込み new RemoveChild( progression.container, loading ), //読み込み完了後ローディングを非表示 new AddChild( progression.container, thunbContainer ), //サムネイルnコンテナを表示 parallelList //サムネイル画像を表示 ); //次へボタン(最後のページじゃなければ表示) if( paged < max ) this.parent.addCommand( new AddChild( progression.container, btnNext ) ); else this.parent.addCommand( new RemoveChild( progression.container, btnNext ) ); //戻るボタン(最初のページじゃなければ表示) if( 1 < paged ) this.parent.addCommand( new AddChild( progression.container, btnPrev ) ); else this.parent.addCommand( new RemoveChild( progression.container, btnPrev ) ); } ) ) return comm; } //flvを表示するコマンドリスト public function flvOpen( flv:String ):SerialList{ this.player = new Player( { flv:flv } ); var comm:SerialList = new SerialList(); comm.addCommand( new Prop( this.thunbContainer, { mouseChildren:false } ), new Prop( this.btnPrev, { mouseEnabled:false } ), new Prop( this.btnNext, { mouseEnabled:false } ), new AddChild( this.progression.container, this.player ) ) return comm; } //flvプを非表示するコマンドリスト public function flvClose():SerialList{ var comm:SerialList = new SerialList(); comm.addCommand( new Prop( this.thunbContainer, { mouseChildren:true } ), new Prop( this.btnPrev, { mouseEnabled:true } ), new Prop( this.btnNext, { mouseEnabled:true } ), new RemoveChild( this.progression.container, this.player ) ) return comm; } } } |