2012年4月18日

Yii Framework: CFormatterを拡張する

CFormatterを拡張して独自のものを作ると便利かもしれないと思い試してみました。作り方の流れは tipshare で紹介されたものがとてもわかりやすいです。

この流れで、具体的にいろいろ CFormatter を拡張したものを作ってみたいと思います。まずは簡単に文字を太くするだけのものを作成。
<?php
/**
* 1. /protected/components/MyFormatter.php を作成。CFormatter を extends する
* 2. format から始まる名前で独自のメソッドを追加
*/
class MyFormatter extends CFormatter
{
public function formatBold($val)
{
return '<b>' . $val . '</b>';
}
}
?>
<?php
/**
* 1. どこかのビューにて Yii::app()->format->formatName('値') を echo する
* ( formatName 箇所は MyFormatter のメソッド名の format を抜いて頭を小文字にしたもの )
* 2. 文字が太くなったか確認
*/
echo Yii::app()->format->bold('Yii Framework');
view raw MyFormatter.php hosted with ❤ by GitHub
次に CGridView と CDetailView でも使えるようなので CDetailView で試してみます。適当にデータベーステーブルを作って Gii でモデルと CRUD を作ります (コントローラの accessRules() は今はいらないので削除) 。
<?php
/**
* 1. /protected/views/book/view.php の任意のカラムに :bold を付け足す
* 2. title カラムが太い文字になっているか確認
*/
?>
<?php $this->widget('zii.widgets.CDetailView', array(
'data' => $model,
'attributes' => array(
'id',
'title:bold',
...
),
)); ?>
view raw view.php hosted with ❤ by GitHub

続いて CDateFormatter::formatDatetime() を使って、数値型 (int) で保存し create_time カラムを独自の日本語表記で表示してみたいと思います。

1334755524 を 2012年04月18日(水) 22時25分 で表記したいとします。

とりあえず、まず CDateFormatter::formatDatetime() がどんな風に日付を表示するかチェックします。以下は、日本語、英語、中国語でのいつくかの表記パターン。
<?php
$time = 1334755524;
/**
* Yii::app()->languageが ja の場合
*/
echo Yii::app()->dateFormatter->formatDatetime($time)."<br />\n";
// 2012/04/1822:25:24
echo Yii::app()->dateFormatter->formatDatetime($time, 'full')."<br />\n";
// 2012年4月18日水曜日22:25:24
echo Yii::app()->dateFormatter->formatDatetime($time, 'long')."<br />\n";
// 2012年4月18日22:25:24
echo Yii::app()->dateFormatter->formatDatetime($time, 'medium')."<br />\n";
// 2012/04/1822:25:24
echo Yii::app()->dateFormatter->formatDatetime($time, 'short')."<br />\n";
// 12/04/1822:25:24
echo Yii::app()->dateFormatter->formatDatetime($time, null)."<br />\n";
// 22:25:24
echo Yii::app()->dateFormatter->formatDatetime($time, 'full', 'full')."<br />\n";
// 2012年4月18日水曜日22時25分24秒 JST
echo Yii::app()->dateFormatter->formatDatetime($time, 'full', 'long')."<br />\n";
// 2012年4月18日水曜日22:25:24 JST
echo Yii::app()->dateFormatter->formatDatetime($time, 'full', 'medium')."<br />\n";
// 2012年4月18日水曜日22:25:24
echo Yii::app()->dateFormatter->formatDatetime($time, 'full', 'short')."<br />\n";
// 2012年4月18日水曜日22:25
echo Yii::app()->dateFormatter->formatDatetime($time, 'full', null)."<br />\n";
// 2012年4月18日水曜日
echo "<hr />\n";
/**
* Yii::app()->languageが en の場合
*/
Yii::app()->setLanguage('en');
echo Yii::app()->dateFormatter->formatDatetime($time)."<br />\n";
// Apr 18, 2012 10:25:24 PM
echo Yii::app()->dateFormatter->formatDatetime($time, 'full')."<br />\n";
// Wednesday, April 18, 2012 10:25:24 PM
echo Yii::app()->dateFormatter->formatDatetime($time, 'long')."<br />\n";
// April 18, 2012 10:25:24 PM
echo Yii::app()->dateFormatter->formatDatetime($time, 'medium')."<br />\n";
// Apr 18, 2012 10:25:24 PM
echo Yii::app()->dateFormatter->formatDatetime($time, 'short')."<br />\n";
// 4/18/12 10:25:24 PM
echo Yii::app()->dateFormatter->formatDatetime($time, null)."<br />\n";
// 10:25:24 PM
echo Yii::app()->dateFormatter->formatDatetime($time, 'full', 'full')."<br />\n";
// Wednesday, April 18, 2012 10:25:24 PM JST
echo Yii::app()->dateFormatter->formatDatetime($time, 'full', 'long')."<br />\n";
// Wednesday, April 18, 2012 10:25:24 PM JST
echo Yii::app()->dateFormatter->formatDatetime($time, 'full', 'medium')."<br />\n";
// Wednesday, April 18, 2012 10:25:24 PM
echo Yii::app()->dateFormatter->formatDatetime($time, 'full', 'short')."<br />\n";
// Wednesday, April 18, 2012 10:25 PM
echo Yii::app()->dateFormatter->formatDatetime($time, 'full', null)."<br />\n";
// Wednesday, April 18, 2012
echo "<hr />\n";
/**
* Yii::app()->languageが zh の場合
*/
Yii::app()->setLanguage('zh');
echo Yii::app()->dateFormatter->formatDatetime($time)."<br />\n";
// 2012-4-18下午10:25:24
echo Yii::app()->dateFormatter->formatDatetime($time, 'full')."<br />\n";
// 2012年4月18日星期三下午10:25:24
echo Yii::app()->dateFormatter->formatDatetime($time, 'long')."<br />\n";
// 2012年4月18日下午10:25:24
echo Yii::app()->dateFormatter->formatDatetime($time, 'medium')."<br />\n";
// 2012-4-18下午10:25:24
echo Yii::app()->dateFormatter->formatDatetime($time, 'short')."<br />\n";
// 12-4-18下午10:25:24
echo Yii::app()->dateFormatter->formatDatetime($time, null)."<br />\n";
// 下午10:25:24
echo Yii::app()->dateFormatter->formatDatetime($time, 'full', 'full')."<br />\n";
// 2012年4月18日星期三JST下午10时25分24秒
echo Yii::app()->dateFormatter->formatDatetime($time, 'full', 'long')."<br />\n";
// 2012年4月18日星期三JST下午10时25分24秒
echo Yii::app()->dateFormatter->formatDatetime($time, 'full', 'medium')."<br />\n";
// 2012年4月18日星期三下午10:25:24
echo Yii::app()->dateFormatter->formatDatetime($time, 'full', 'short')."<br />\n";
// 2012年4月18日星期三下午10:25
echo Yii::app()->dateFormatter->formatDatetime($time, 'full', null)."<br />\n";
// 2012年4月18日星期三
view raw hoge.php hosted with ❤ by GitHub

国によって表記が全く違うのがわかります。あと Yii のバージョンが 1.1.10 時点では日本語表記部分で、日付と時間がくっ付いているバグもいくつかあります (1.1.11 以降では日本語表記のバグは修正される模様です) 。とりあえず、デフォルトでは 2012年04月18日(水) 22時25分 と表記できないようなので、コアの i18n の日本語ファイルを上書きする形で、上記の日付のような表記にしてみたいと思います。

やり方の順序

  1.  framework/i18n/data/ja.php と ja_jp.php を /protected/i18n/data 下にコピペ
  2. en 関係と、その他、国際化するであろう、ファイルもコピペ
  3. /protected/main/config.php に 'localeDataPath' => 'protected/i18n/data/' と書く
これでロケールデータが呼ばれた場合、コアではなく protected 下の i18n のものが呼ばれるようになります。それでは、日本語表記の修正をしていきます。
<?php
return array (
...
'weekDayNames' =>
array (
'wide' =>
array (
// 0 => '日曜日',
// 1 => '月曜日',
// 2 => '火曜日',
// 3 => '水曜日',
// 4 => '木曜日',
// 5 => '金曜日',
// 6 => '土曜日',
0 => '(日)',
1 => '(月)',
2 => '(火)',
3 => '(水)',
4 => '(木)',
5 => '(金)',
6 => '(土)',
),
...
...
'dateFormats' =>
array (
// 'full' => 'y年M月d日EEEE',
'full' => 'y年MM月dd日',
'long' => 'y年M月d日',
'medium' => 'yyyy/MM/dd',
'short' => 'yy/MM/dd',
),
'timeFormats' =>
array (
'full' => 'H時mm分ss秒 zzzz',
'long' => 'H:mm:ss z',
'medium' => 'H:mm:ss',
// 'short' => 'H:mm',
'short' => 'HH時mm分',
),
// 'dateTimeFormat' => '{1}{0}',
'dateTimeFormat' => '{1} {0}',
'amName' => '午前',
'pmName' => '午後',
'orientation' => 'ltr',
...
view raw ja.php hosted with ❤ by GitHub

コメントアウトしてあるものはデフォルトの値です。これで
echo Yii::app()->dateFormatter->formatDatetime($time, 'full', 'short');
と書いている箇所は 2012年04月18日(水) 22時25分 と表示されるはずです。

最後に目的を達成した日付表示を MyFormatter に付け足すと CGridView や CDetailView  でも使えるようになるので、便利です!また CGridView や CDetailView ではなく直接表示したい場合は記述が長くなるので Yii Wiki: Use shortcut functions to reduce typing  を使って短く記述できるようにすればOKかなと思います。

参考リンク

0 件のコメント:

コメントを投稿