FuelPHPでRedisを使用する
FuelPHPには、標準でRedisクラスが用意されている為、特別な事をする必要はなく、そのままRedisへアクセスが可能です。
例によって、ソート済みセット型を使用した、ランキング風のサンプルで試しました。
以下は、ユーザー名と年齢のリストをソート済みセット型に追加し、要素を取得するサンプルになります。
<?php class Controller_Redistest extends Controller { public function action_index() { $redis = Redis::instance('default'); $staff = array( 'staff1' => 30, 'staff2' => 25, 'staff3' => 42, 'staff4' => 60, 'staff5' => 38 ); foreach ($staff as $name => $age) { // 年齢をスコアとして、スタッフ名をメンバーとして登録 $redis->zadd('mysort', $age, $name); } // 年齢の昇順リスト $list = $redis->zrange('mysort', 0, count($staff)); // 年齢の降順リスト $rlist = $redis->zrevrange('mysort', 0, count($staff)); // 昇順の場合の staff4 の順位(ランクが0から始まる為、1を足す) $rank = $redis->zrank('mysort', 'staff4') + 1; // 降順の場合の staff4 の順位(ランクが0から始まる為、1を足す) $rrank = $redis->zrevrank('mysort', 'staff4') + 1; ... } }
Redis::instanceにセットする名前は『fuel/app/config/db.php』の『redis』に設定した名前になります。
'redis' => array( 'default' => array( 'hostname' => '127.0.0.1', 'port' => 6379 ) ),
PHPでRedisを試す
危険なほどのスピードを持つというKVS『Redis』。
redisドキュメント日本語訳を見て頂くと、Redisの持っている機能の概要が書いてあります。
インストール
自分の環境(CentOS 6.2)では、yumでインストールが可能でした。
# yum install redis # cp /etc/redis.conf /etc/redis.conf.bak
ソースからインストールする場合の手順と起動方法について、以下のページに記載があります。
http://redis.io/download
$ wget http://redis.googlecode.com/files/redis-2.4.15.tar.gz $ tar xzf redis-2.4.15.tar.gz $ cd redis-2.4.15 $ make
設定ファイル
yumでインストールを行った場合、設定ファイルは『/etc』配下に設置されます。
# cp /etc/redis.conf /etc/redis.conf.bak
起動
redisを起動します。
(デフォルトでは『127.0.0.1:6379』がオープン)
# /etc/rc.d/init.d/redis start # chkconfig redis on
次に、インストール手順に従い接続テストを行い、setとgetが問題なく動作する事を確認します。
$ redis-cli redis 127.0.0.1:6379> set foo bar OK redis 127.0.0.1:6379> get foo "bar" redis 127.0.0.1:6379> exit
これで、redisを試す環境が出来ました。
PHPからの接続
http://redis.io/clientsを見ると、様々な言語のクライアントリストが表示されます。
今回は『Predis』で、簡単な接続のみ試しました。
$ wget -O predis.zip https://github.com/nrk/predis/zipball/v0.7 $ unzip predis.zip
PHP側では、伸張したディレクトリ内に存在する『autoload.php』をrequireします。
下記が、getとsetのサンプルです。
<?php require 'nrk-predis-4bc6f58/autoload.php'; Predis\Autoloader::register(); // 接続 $redis = new Predis\Client('tcp://127.0.0.1:6379'); // 値をセット $redis->set('foo', 'bar'); // 値を取得 echo $redis->get('foo');
コマンドリファレンスを参考に、後は以下の形式で実行するだけです。
$redis->{コマンド}(パラメータ...); 例) $redis->hset('myhash', 'name', 'myname'); $redis->hget('myhash', 'name');
FuelPHPのRestコントローラ
FuelPHPにはRestコントローラというものがあります。
使い方は簡単で、『Controller_Rest』を継承したコントローラを作成し、その中に処理を入れていくだけで、以下のフォーマットの出力が可能になります。
(core/classes/format.phpを見ると、jsonpやらyamlやらもあるようです)
コントローラに追加していくメソッド名と、アクセスする為のURLは以下のようになります。
メソッド名) public function {HTTPメソッド}_{任意の名前} URL) /{コントローラ名}/{任意の名前}.{フォーマット} 例) public function get_list -> /xxx/list.xml -> /xxx/list.json
サンプルと出力内容
公式ドキュメントのサンプルは、以下のようになっています。
<?php class Controller_Test extends Controller_Rest { public function get_list() { $this->response(array( 'foo' => Input::get('foo'), 'baz' => array( 1, 50, 219 ), 'empty' => null )); } }
上記に『xml』『json』でアクセスした結果が以下になります。
xml
/test/list.xml?foo=bar
<?xml version="1.0" encoding="utf-8"?> <xml> <foo>bar</foo> <baz> <item>1</item> <item>50</item> <item>219</item> </baz> <empty></empty> </xml>
json
/test/list.json?foo=bar
{ "foo":"bar", "baz":[1,50,219], "empty":null }
CSV
csvの場合、Responseに対しに、以下のような配列で渡す必要があるようです。
<?php ... public function get_list() { $data = array( array(1, 2, 3, 4), array("aaa", "bbb", "ccc", Input::get('foo')) ); $this->Response($data); }
『/test/list.csv?foo=bar』にアクセスすると、csvのダウンロードが始まり、出力されたcsvの中身は以下のようになっています。
"1","2","3","4" "aaa","bbb","ccc","bar"
どうでしょう?Restコントローラ
FuelPHPでページキャッシュ
FuelPHPでページを丸々キャッシュする方法を調べたところ、『fuel-pagecache』というのを作っている方がいたので、試してみました。
fuel-pagecache)
https://github.com/xavividal/fuel-pagecache
以下のような動作になっています。
- Templateコントローラで出力したコンテンツを静的ファイルに出力
- mod_rewriteで静的ファイルに振り分け
1度キャッシュしてしまうと、その後はmod_rewriteでの振り分けになる為、当然ながらコンテンツ更新が行われてもキャッシュはクリアされません。
加えて、ページキャッシュの有効期限等も存在しない為、ページ更新時はページキャッシュを削除してやる必要があります。
以下、設定内容になります。
ファイル配置
githubよりfuel-pagecacheを取得し、以下にそれぞれ配置します。
Autoloader設定
『fuel/app/bootstrap.php』に以下を記述します。
Autoloader::add_core_namespace('Xvp'); Autoloader::add_classes(array( ... 'Xvp\\Pagecache' => __DIR__.'/classes/pagecache.php' ));
キャッシュディレクトリ作成
ドキュメントルート直下にキャッシュ用ディレクトリを作成します。
$ mkdir {ドキュメントルート}/cache $ chmod 777 {ドキュメントルート}/cache
Controller
ページキャッシュを行いたいTemplateコントローラにて、『before()』『after()』の設定を行い、キャッシュしたいaction内で『$this->pagecache->enableCache();』を呼び出します。
<?php class Controller_Cachetest extends Controller_Template { public function before() { parent::before(); $this->pagecache = new Pagecache(); $this->pagecache->setResponse($this->response); $this->pagecache->setRequest($this->request); } public function after($response) { $response = parent::after($response); if ($this->pagecache->isCacheable()) { $this->pagecache->cache($_SERVER['REQUEST_URI']); } return $response; } public function action_index() { $this->pagecache->enableCache(); ... } }
.htaccess設定
.htaccessにて以下の設定を行います。
RewriteRule ^/(.*)/$ /$1 [QSA] RewriteRule ^$ cache/index.html [QSA] RewriteRule ^([^.]+)/$ cache/$1/index.html [QSA] RewriteRule ^([^.]+)$ cache/$1/index.html [QSA] RewriteCond %{REQUEST_FILENAME} -s [OR] RewriteCond %{REQUEST_FILENAME} -l [OR] RewriteCond %{REQUEST_FILENAME} -f [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^.*$ - [NC,L] RewriteRule ^.*$ index.php [NC,L]
上記設定後、『$this->pagecache->enableCache()』を設定したページにアクセスすると、cacheディレクトリに静的ファイルが出力され、次回以降のアクセスは静的ファイルが参照される事になります。
cacheディレクトリ内静的ファイルに、適当な文字列を記述するなどして、キャッシュに振り分けられてるかの確認が可能です。
ページャー(Pagination)のリンク表示数
FuelPHPでページャー(Pagination)に書いた通り、FuelPHP標準のPaginationでは、カレントページより前のリンク表示数は、『num_links』で設定した値 - 1を表示するようになっています。(後はnum_linksで設定した数)
例)
これを、出来ればカレントページ番号を挟み、前後とも『num_links』で設定した数だけ、リンクを表示したいと思うのは自分だけでしょうか。
設定自体は、Paginationクラス(fuel/core/class/pagination.php)内page_linksに以下の修正を加えれば完了です。
$start = ((static::$current_page - static::$num_links) > 0) ? static::$current_page - (static::$num_links - 1) : 1; ↓ $start = ((static::$current_page - static::$num_links) > 0) ? static::$current_page - (static::$num_links - 0) : 1;
普通は、この修正だけでもコアを拡張?
FuelPHPでページャー(Pagination)
FuelPHPでページャー
FuelPHP標準のPaginationを使用したページャーを実装してみます。
想定バージョン) FuelPHP 1.3
CodeIgniterの標準のページャーは、offsetがURLに入り、残念な感じになっていましたが、FuelPHPではそんな事はないようです。
日本語設定
まずは、前後リンクの日本語設定を行います。
$ vi fuel/app/lang/ja/pagination.php
pagination.phpに下記を記述します。
<?php return array( 'previous' => '前へ', 'next' => '次へ', );
Controller
Controllerでは、ページャー関連の設定をPaginationクラスに渡し、ページャーを生成します。(設定にページ下部参照)
データ取得時のlimit、offsetは下記で取得が可能です。
- Pagination::$per_page
- Pagination::$offset
<?php class Controller_Welcome extends Controller { public function action_index() { $view = View::forge('welcome/index'); $config = array( 'pagination_url' => 'pager/index', 'total_items' => DB::count_records('users'), 'per_page' => 5, 'uri_segment' => 3, 'num_links' => 5, 'template' => array( 'wrapper_start' => '<ul class="pager"> ', 'wrapper_end' => '</ul>', 'page_start' => '', 'page_end' => '', 'previous_start' => '<li class="prev">', 'previous_end' => '</li>', 'previous_inactive_start' => '<li class="prev">', 'previous_inactive_end' => '</li>', 'previous_mark' => '<< ', 'next_start' => '<li class="next">', 'next_end' => '</li>', 'next_inactive_start' => '<li class=next">', 'next_inactive_end' => '</li>', 'next_mark' => ' >>', 'active_start' => '<li><em>', 'active_end' => '</em></li>', 'regular_start' => '<li>', 'regular_end' => '</li>' ) ); Pagination::set_config($config); $view->set_safe('pager', Pagination::create_links()); $data = DB::select()->from('users') ->limit(Pagination::$per_page) ->offset(Pagination::$offset) ->execute() ->as_array(); return $view; } }
Template
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style type="text/css"> * { margin: 0; padding: 0; font-style: normal; list-style: none; } body { font: 70% Arial, Helvetica, sans-serif; } ul.pager { margin: 10px; } ul.pager li { float: left; margin-right: 5px; border: 1px #3366FF solid; font-weight: bold; } ul.pager li.prev, ul.pager li.next { border: none; } ul.pager li a { position: relative; display: block; padding: 3px 8px; color: #3366FF; } ul.pager li a:link, ul.pager li a:visited { text-decoration: none; } ul.pager li a:hover, ul.pager li a:active { background-color: #AADDFF; text-decoration: none; } ul.pager li em { display: block; padding: 3px 8px; background: #3366FF; color: #FFFFFF; } </style> </head> <body> <?php echo $pager ?> </body> </html>
出力内容
以下のようなページャーが出力されます。
HTMLは以下のようになります。
<ul class="pager"> <li class="prev"><< 前へ </li> <li><em>1</em></li> <li><a href="http://hoge.com/welcome/index/2">2</a></li> <li><a href="http://hoge.com/welcome/index/3">3</a></li> <li><a href="http://hoge.com/welcome/index/4">4</a></li> <li><a href="http://hoge.com/welcome/index/5">5</a></li> <li><a href="http://hoge.com/welcome/index/6">6</a></li> <li class="next"><a href="http://hoge.com/welcome/index/2">次へ >></a></li> </ul>
Pagination設定内容
Paginationクラスに渡す設定一覧になります。(templateのみ配列形式)
※num_linksは、カレントページ番号の前が『num_linksで設定した値 - 1』個表示されるようです。(num_linksが5の場合、カレントページの前は4つリンクが表示される)
config
pagination_url | 生成するURL |
total_items | 対象件数 |
per_page | 1ページ当たり表示件数 |
num_links | カレントページの前後それぞれに表示するリンク数 |
uri_segment | ページ番号パラメータを挿入する位置 |
current_page | ページ番号指定? |
template | HTMLタグ設定(以下参照) |
config.template
wrapper_start/wrapper_end | ページャー全体を囲むタグ |
page_start/page_end | ページ番号全体を囲むタグ |
previous_start/previous_end | previousリンクを囲むタグ |
previous_inactive_start/previous_inactive_end | previousリンク無効時のタグ |
previous_mark | previous文言の前に出力 |
next_start/next_end | nextリンクを囲むタグ |
next_inactive_start/next_inactive_end | nextリンク無効時のタグ |
next_mark | next文言の後に出力 |
active_start/active_end | 選択ページのページ番号を囲むタグ |
regular_start/regular_end | 選択ページ以外のページ番号を囲むタグ |
num_linksの前の個数が気になる...