Ethnaでのgettextによる国際化

extentionのgettextを利用可能にする

php_gettext.dllのコメントアウトはずすとか--with-gettextでコンパイルするとか

gettextのmoファイルを下記に配置

プロジェクトディレクトリ/locale/ja/LC_MESSAGES/{APPID}.mo
APPIDは大文字

テンプレートの国際化

Smartyのmodifierプラグインを利用する

{"message"|i18n}

アクションフォームの国際化

{APPID}_ViewClassのgetFormNameメソッドをオーバーライド

    function getFormName($name, $action, $params)
    {
        $af =& $this->_getHelperActionForm($action, $name);
        if ($af === null) {
            return $name;
        }
        return $af->getName($name);
    }

アクションフォームのフォーム定義
nameプロパティを書くとそちらが優先されるので書かない

    var $form = array(
       'name' => array(
           'type'           => VAR_TYPE_STRING,
           'form_type'      => FORM_TYPE_TEXT,
           'required'       => true,
           'required_error' => 'name(required)',
       ),
    );


9割は使わないであろう機能でしょうが、使おうと思えばそれほど苦労せず利用できそうでEthnaっぽいなと思いました。

foreach最強伝説

Cバリバリやってましたというオサーンがwhileeachを連発して「この方が見やすい」と謎なことをのたまうのでベンチマーク結果を投げつけました。

元ネタ→http://labs.cybozu.co.jp/blog/tsuruoka/anubis/blog_show/22:PEAR::Benchmarkでプログラムの実行時間を測定する

<?php
require_once 'Benchmark/Timer.php';
$timer = new Benchmark_Timer();
$timer->start();
$target_function = array(
    'bench_array_sum',
    'bench_for_loop',
    'bench_for_precount',
    'bench_while_loop',
    'bench_while_precount',
    'bench_while_currentshift',
    'bench_while_shift',
    'bench_while_next',
    'bench_foreach_loop',
    'bench_foreach_withkey',
    'bench_whileeach'
);
$target_sum = 0;
$target_array = array();
for($i = 0; $i < 4000; $i++) {
    $data = rand(1,10);
    $target_array[] = $data;
    $target_sum += $data;
}
$timer->setMarker('make_data');
foreach ($target_function as $function) {
    $result = $function($target_array);
    if ($result != $target_sum) {
        exit($function . " return invalid value\n");
    }
    $timer->setMarker($function);
}
$timer->stop();
$timer->display();
function bench_array_sum($target_array)
{
    return array_sum($target_array);
}
function bench_for_loop($target_array)
{
    $sum = 0;
    for ($i = 0; $i < count($target_array); $i++) {
        $sum += $target_array[$i];
    }
    return $sum;
}
function bench_for_precount($target_array)
{
    $sum = 0;
    $target_array_count = count($target_array);
    for ($i = 0; $i < $target_array_count; $i++) {
        $sum += $target_array[$i];
    }
    return $sum;
}
function bench_while_loop($target_array)
{
    $i = 0;
    $sum = 0;
    while ($i < count($target_array)) {
        $sum += $target_array[$i];
        $i++;
    }
    return $sum;
}
function bench_while_precount($target_array)
{
    $i = 0;
    $sum = 0;
    $target_array_count = count($target_array);
    while ($i < $target_array_count) {
        $sum += $target_array[$i];
        $i++;
    }
    return $sum;
}
function bench_while_shift($target_array)
{
    $sum = 0;
    while (NULL !== ($value = array_shift($target_array))) {
        $sum += $value;
    }
    return $sum;
}
function bench_while_currentshift($target_array)
{
    $sum = 0;
    while (current($target_array) !== false) {
        $sum += array_shift($target_array);
    }
    return $sum;
}
function bench_while_next($target_array)
{
    $sum = 0;
    $sum+= current($target_array);
    while (($value = next($target_array)) !== false) {
        $sum += $value;
    }
    return $sum;
}
function bench_foreach_loop($target_array)
{
    $sum = 0;
    foreach ($target_array as $value) {
        $sum += $value;
    }
    return $sum;
}
function bench_foreach_withkey($target_array)
{
    $sum = 0;
    foreach ($target_array as $key => $value) {
        $sum += $value;
    }
    return $sum;
}
function bench_whileeach($target_array)
{
    $sum = 0;
    while (list($key, $value) = each($target_array)) {
        $sum += $value;
    }
    return $sum;
}

Core 2 Duo T5500、1GBでphp5.1.6での結果。
xdebugは入ってますが、APCとかeAcceleratorとかハイカラなものは入ってません。

-----------------------------------------------------------------------
marker                     time index            ex time         perct
-----------------------------------------------------------------------
Start                      1210581808.81469700   -                0.00%
-----------------------------------------------------------------------
make_data                  1210581808.84215500   0.027458         5.89%
-----------------------------------------------------------------------
bench_array_sum            1210581808.84234800   0.000193         0.04%
-----------------------------------------------------------------------
bench_for_loop             1210581808.86441500   0.022067         4.73%
-----------------------------------------------------------------------
bench_for_precount         1210581808.86751600   0.003101         0.67%
-----------------------------------------------------------------------
bench_while_loop           1210581808.88944700   0.021931         4.71%
-----------------------------------------------------------------------
bench_while_precount       1210581808.89236800   0.002921         0.63%
-----------------------------------------------------------------------
bench_while_currentshift   1210581809.06808400   0.175716        37.70%
-----------------------------------------------------------------------
bench_while_shift          1210581809.22760800   0.159524        34.23%
-----------------------------------------------------------------------
bench_while_next           1210581809.24940900   0.021801         4.68%
-----------------------------------------------------------------------
bench_foreach_loop         1210581809.25163700   0.002228         0.48%
-----------------------------------------------------------------------
bench_foreach_withkey      1210581809.25413200   0.002495         0.54%
-----------------------------------------------------------------------
bench_whileeach            1210581809.28071000   0.026578         5.70%
-----------------------------------------------------------------------
Stop                       1210581809.28076400   0.000054         0.01%
-----------------------------------------------------------------------
total                      -                     0.466067       100.00%
-----------------------------------------------------------------------

foreach最強伝説。

mb_encode_mimeheader()の使い方

mb_encode_mimeheader()は、mbstring.internal_encoding*1から第二引数の文字コード、またはmbstring.languageで指定した言語に合った文字コード(JapaneseならISO-2022-JP)に変換した上でbase64エンコードエンコード情報を付加します。
よって、レンタルサーバphp.iniの設定が不十分な場合、個別に設定したい場合は、関数をコールする前にmb_language()、mb_internal_encoding()で値を設定する必要があります。


よく見かけますが、第一引数に渡す文字列をISO-2022-JPへ変換する必要はありません。
正しくは必要がないのではなく、やってはいけません。

<?php
mb_language('ja');
mb_internal_encoding('UTF-8');

$subject = '十分に長いsubjectでのテストを行います、まる';

echo mb_encode_mimeheader($subject) . "\n";
echo mb_encode_mimeheader(mb_convert_encoding($subject, 'ISO-2022-JP', 'UTF-8')) . "\n";
?>

結果。

=?ISO-2022-JP?B?GyRCPT1KLCRLRDkkJBsoQnN1YmplY3QbJEIkRyROJUYlOSVIJHIbKEI=?=
 =?ISO-2022-JP?B?GyRCOVQkJCReJDkhIiReJGsbKEI=?=
=?ISO-2022-JP?B?GyRCPT1KLCRLRDkkJBsoQnN1YmplY3QbJEIkRyROJUYlOSVIJHI5VCQk?=
 =?ISO-2022-JP?B?JF4kOSEiJF4kaxsoQg==?=

なんか後半が違います。


mb_decode_mimeheader()は大方の予想通りmb_encode_mimeheader()と逆の動作をしそうです。

<?php
mb_language('ja');
mb_internal_encoding('UTF-8');

$subject = '十分に長いsubjectでのテストを行います、まる';

$utf = mb_encode_mimeheader($subject);
$iso = mb_encode_mimeheader(mb_convert_encoding($subject, 'ISO-2022-JP', 'UTF-8'));

echo mb_decode_mimeheader($utf) . "\n";
echo mb_decode_mimeheader($iso) . "\n";
?>

結果。

十分に長いsubjectでのテストを行います、まる
十分に長いsubjectでのテストを行い$^$9!"$^$k


そもそも、mb_encode_mimeheader()を通した段階で結果が違うのがおかしいですね。

<?php
mb_language('ja');
mb_internal_encoding('UTF-8');

$subject = '十分に長いsubjectでのテストを行います、まる';

mb_internal_encoding('ISO-2022-JP');
$iso = mb_encode_mimeheader(mb_convert_encoding($subject, 'ISO-2022-JP', 'UTF-8'));
echo $iso . "\n";
mb_internal_encoding('UTF-8');
echo mb_decode_mimeheader($iso) . "\n";
?>

結果。

=?ISO-2022-JP?B?GyRCPT1KLCRLRDkkJBsoQnN1YmplY3QbJEIkRyROJUYlOSVIJHIbKEI=?=
 =?ISO-2022-JP?B?GyRCOVQkJCReJDkhIiReJGsbKEI=?=
十分に長いsubjectでのテストを行います、まる

mb_encode_mimeheader()に渡す文字列はISO-2022-JPに変換するな。


自分のとこのblogだと周知されなそうなのではてダにも。
はてな市民権が欲しいんです?

*1:ISO-2022-JPエンコードしたもの投げたときの動作みるとdetect_ order?

PHPのメモリの使い方

unset()をしているが、メモリの消費量は変化しない。

えぇぇぇ!ということで調べてみた。

<?php
$memory_usage = memory_get_usage();
$arr = range(1,10000);
echo memory_get_usage() - $memory_usage . "\n"; // 785888
unset($arr);
echo memory_get_usage() - $memory_usage . "\n"; // 65072
?>

ちゃんと開放されてます。つか、オーバーヘッドひどいな。

<?php
$memory_usage = memory_get_usage();
$arr = range(1,10000);
echo memory_get_usage() - $memory_usage . "\n"; // 785896
$arr2 =& $arr;
echo memory_get_usage() - $memory_usage . "\n"; // 786056
unset($arr);
echo memory_get_usage() - $memory_usage . "\n"; // 786056
?>

たぶん開放されない?と思ってるのはこれのせいじゃないのでしょうか。
リファレンスとは?
>>リファレンスは、Unix ファイルシステムの ハードリンクのようなものであると考えられます。<<

<?php
$memory_usage = memory_get_usage();
$arr = range(1,10000);
echo memory_get_usage() - $memory_usage . "\n"; // 785896
$arr2 =& $arr;
echo memory_get_usage() - $memory_usage . "\n"; // 786056
$arr = null;
echo memory_get_usage() - $memory_usage . "\n"; // 65200
?>

nullっちゃうとかどうでしょう。


ついでに。

<?php
$memory_usage = memory_get_usage();
$arr = range(1,10000);
echo memory_get_usage() - $memory_usage . "\n"; // 785896
$arr2 = $arr;
echo memory_get_usage() - $memory_usage . "\n"; // 786032
count($arr2);
echo memory_get_usage() - $memory_usage . "\n"; // 786032
next($arr2);
echo memory_get_usage() - $memory_usage . "\n"; // 1331624
?>

代入した段階ではメモリ確保されないだっけ?
マニュアル見つけられず。


PHPバッチ処理書くのは他の言語に自信がない人d、うわ、何をするー。

PEAR::Pagerがきもい

http://d.hatena.ne.jp/elf/20070531/1180596453

ふいた。
オプションの「httpMethod」がPOSTの場合、生成されたリンクがjavascriptを駆使してがんばってPOSTしてた。

<?php
require_once 'Pager.php';
$items = range('a', 'z');
$options = array(
    'mode'          => 'Sliding',
    'itemData'      => $items,
    'urlVar'        => 'p',
);
$pager = Pager::factory($options);
$r_items = $pager->getPageData();
$links = $pager->getLinks();
?>
<a href="<?php print $_SERVER['SCRIPT_NAME']; ?>?p=2&hoge=hoge">get</a>
<form action="<?php print $_SERVER['SCRIPT_NAME']; ?>" method="POST">
	<input type="hidden" name="p" value="2" />
	<input type="hidden" name="hoge" value="hoge" />
	<input type="submit" value="post"/>
</form>
<?php
foreach($r_items as $item) {
    print $item . "<br />\n";
}
print $links['all'] . "<br />\n";
?>

「httpMethod」を設定しなかった場合、$_SERVER['REQUEST_METHOD']から判断するので意図しない動作になる場合があります。
検索結果をページングさせようと思った場合などに。

$options = array(
    'mode'          => 'Sliding',
    'itemData'      => $items,
    'urlVar'        => 'p',
    'httpMethod'    => 'GET',
);

オプション「httpMethod」に「GET」を指定してあげればリンクはjavascriptの怪しいリンクとはならないのですが、自動で引き回すパラメータは$_GETに存在するパラメータのみとなります。
ページ用パラメータは$_REQUESTからとってきているのに。

$options = array(
    'mode'          => 'Sliding',
    'itemData'      => $items,
    'urlVar'        => 'p',
    'httpMethod'    => 'GET',
    'importQuery'   => false,
    'extraVars'     => $_REQUEST,
);

「importQuery」でパラメータの持ちまわしをやめ、「extraVars」で持ちまわしたいパラメータ配列を設定することでこの値を自動的に引き回すようになります。


$_REQUESTは$_COOKIEも含むので$_GETと$_POSTをマージしてあげるのがいいと思います。


Pagerめんど。