アーカイブ

2008 年 4 月 のアーカイブ

PEAR::Services_Yahoo_JP

2008 年 4 月 30 日 コメントはありません

PEAR::Services_Yahoo_JP
なんぞこれ

カテゴリー: 日記 タグ:

PHPマニュアルがバージョンアップ

2008 年 4 月 28 日 コメントはありません

関数リファレンスに親カテゴリができてた。

PHPマニュアルを眺めてたらPHP5.3、PHP6.0からの内容がいろいろ追加されてた。
名前空間
遅延静的束縛 (Late Static Bindings)

あとエラー例外のページも追加されてた。
ErrorException
前はこっそりあっただけなのに。
PHPの標準関数のエラーを例外エラーとしてthrowするのでtry-catchで楽です。


<?php
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler("exception_error_handler");

echo "開始\n";
try {
    fopen();
    strpos();
} catch(Exception $e) {
    $e->getMessage() . "\n";
}
echo "終了\n";
# 開始
# fopen() expects at least 2 parameters, 0 given
# 終了 

例外といえばタイプヒンティング利用すれば処理もいろいろできます。


<?php
try {
    throw new LogicException('例外');
} catch (ErrorException $e) {
    echo 'エラー' . $e->getMessage(); 
} catch (LogicException $e) {
    echo 'ロジック' . $e->getMessage(); }
# ロジック例外 

カテゴリー: 日記 タグ:

Ethnaのフォーム定義をyamlで書く

2008 年 4 月 28 日 コメントはありません

アクションフォーム毎に設定とか糞なのでプロジェクトのアクションフォームに設定するように。
せっかくなのでプラグイン化。

yamlファイルはetc以下におくことにしました
元になるフォーム定義はこれ


    var $form = array(
        'login_id' => array(
            'type'          => VAR_TYPE_STRING,
            'form_type'     => FORM_TYPE_TEXT,
            'name'          => 'ログインID',
            'required'      => true,
        ),
        'password' => array(
            'type'          => VAR_TYPE_STRING,
            'form_type'     => FORM_TYPE_PASSWORD,
            'name'          => 'パスワード',
            'required'      => true,
        ),
        'login' => array(
        ),
    );  

□1□ 1.{appid}/libにspycの0.3betaをインストール

□2□ {appid}/etcにアクションフォームのクラス名小文字.yaml(今回はsample_form_login.yaml)を作成


login_id:
  type: VAR_TYPE_STRING
  form_type: FORM_TYPE_TEXT
  name: ログインID
  required: true
password:
  type: VAR_TYPE_STRING
  form_type: FORM_TYPE_PASSWORD
  name: パスワード
  required: true
login:

□3□ {appid}/app/pluginに以下のファイルを作る
Lowtech_Plugin_Parser.php


<?php
/**
 * Lowtech_Plugin_Parser.php
 *
 * @author cockok <cockok@cheki.net>
 * @package Lowtech
 * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
 * @version $id$
 */

/**
 * Lowtech_Plugin_Parser
 *
 * @author cockok <cockok@cheki.net>
 * @package Lowtech
 * @version $id$
 */
class Lowtech_Plugin_Parser
{
    /** @var object Ethna_Controller コントローラオブジェクト */
    var $controller;

    /**
     * Lowtech_Plugin_Parserのコンストラクタ
     *
     * @param object Ethna_Controller $controller コントローラオブジェクト
     * @access public
     * @return void
     */
    function Lowtech_Plugin_Parser(&$controller)
    {
        $this->controller =& $controller;
    }

    /**
     * Lowtech_Plugin_Parserのコンストラクタ
     *
     * @param string $path 対象のパス
     * @access public
     * @return Ethna_Error object
     */
    function load($path)
    {
        return Ethna::raiseError('override!');
    }
}
?>

Parser/Lowtech_Plugin_Parser.php


<?php
/**
 * Lowtech_Plugin_Loader_Yaml.php
 *
 * @author cockok <cockok@cheki.net>
 * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
 * @package Lowtech
 * @version $id$
 */

/**
 * spyc 0.3beta
 * http://spyc.sourceforge.net/
 */
if (substr(PHP_VERSION, 0, 1) >= 5) {
    require_once 'spyc/spyc.php5';
} else {
    require_once 'spyc/spyc.php';
}

/**
 * Lowtech_Plugin_Parser_Yaml
 *
 * @author cockok <cockok@cheki.net>
 * @package Lowtech
 * @version $id$
 */
class Lowtech_Plugin_Parser_Yaml extends Lowtech_Plugin_Parser
{
    /**
     * Lowtech_Plugin_Parserのコンストラクタ
     *
     * @param string $path 対象のパス
     * @access public
     * @return mixed failed Ethna_Error
     */
    function load($path)
    {
        // ファイルの更新日時の取得
        clearstatcache();
        if (is_readable($path) === false
                || ($st = stat($path)) === false) {
            return Ethna::raiseNotice('fopen failed ' . $path);
        }
        $mtime = $st[9];
        // キャッシュキーの作成
        $key = md5($path);
        // キャッシュマネージャ
        $plugin =& $this->controller->getPlugin();
        $cache_manager =& $plugin->getPlugin('Cachemanager', 'Localfile');
        // 更新日時以降のキャッシュをチェック
        if ($cache_manager->isCached($key)
                && $mtime < $cache_manager->getLastModified($key)) {
            // キャッシュがヒット
            $r = $cache_manager->get($key);
        } else {
            // 有効なキャッシュが見つからなかった
            $r = Spyc::YAMLLoad($path);
            // データをキャッシュする
            $cache_manager->set($key, $r);
        }
        return $r;
    }
}
?>

□4□ コントローラの$plugin_search_appidsに利用するアプリケーションID(Lowtech)を追加


$plugin_search_appids = array(
    '{appid}', 'Lowtech', 'Ethna',
); 

□5□ アクションフォームのコンストラクタをオーバーライド


    function {appid}_Form_Login(&$controller)
    {
        // yamlプラグイン
        $plugin =& $controller->getPlugin();
        $loader =& $plugin->getPlugin('Parser', 'Yaml');
        // form値の上書き
        $r = $loader->load(BASE . '/etc/' . strtolower(get_class($this)) . '.yaml');
        if (!Ethna::isError($r)) {
            $this->form = $r;
        }
        // type, form_typeの定数を補正
        $constants = get_defined_constants();
        foreach ($this->form as $name => $value) {
            foreach ($this->def as $k) {
                if (isset($value[$k]) && in_array($k, array('type', 'form_type'))
                        && array_key_exists($value[$k], $constants)) {
                    $this->form[$name][$k] = $constants[$value[$k]];
                }
            }
        }
        // オーバーライド
        parent::Ethna_ActionForm($controller);
    } 

カテゴリー: 日記 タグ:

アクションフォームのフォーム値をyamlで書きたい!

2008 年 4 月 26 日 コメント 1 件

アクションフォームのフォーム値をyamlで書きたいとは配列好きなので思ったことなかったのですが、PHP勉強会でEthnaの話題がでるということで半年振りくらいに触ってみる。
半年振りでも変わらないEthnaステキ!

yamlファイルはアクションと同ディレクトリに小文字ファイル名で。

これが元。


class Sample_Form_Login extends Sample_ActionForm
{
    /** @var    bool    バリデータにプラグインを使うフラグ */
    var $use_validator_plugin = true;

    /**
     *  @access private
     *  @var    array   フォーム値定義
     */
    var $form = array(
        'login_id' => array(
            'type'          => VAR_TYPE_STRING,
            'form_type'     => FORM_TYPE_TEXT,
            'name'          => 'ログインID',
            'required'      => true,
        ),
        'password' => array(
            'type'          => VAR_TYPE_STRING,
            'form_type'     => FORM_TYPE_PASSWORD,
            'name'          => 'パスワード',
            'required'      => true,
        ),
        'login' => array(
        ),
    ); 

1.lib以下にspycの3.0betaぶち込む
2.コントローラでrequire


/** アプリケーションライブラリのインクルード */
require_once 'Ethna/Ethna.php';
require_once 'Sample_Error.php';
require_once 'Sample_ActionClass.php';
require_once 'Sample_ActionForm.php';
require_once 'Sample_ViewClass.php';

require_once 'spyc/spyc.php';
//require_once 'spyc/spyc.php5'; 

3.アクションと同位置にファイル名.yaml(今回はlogin.yaml)を作成


login_id:
  type: VAR_TYPE_STRING
  form_type: FORM_TYPE_TEXT
  name: ログインID
  required: true
password:
  type: VAR_TYPE_STRING
  form_type: FORM_TYPE_PASSWORD
  name: パスワード
  required: true
login:

4.アクションフォームのコンストラクタをオーバーライド


    function Sample_Form_Login(&$controller)
    {
        parent::Sample_ActionForm($controller);

        $yaml_path = dirname(__FILE__).DIRECTORY_SEPARATOR.strtolower(substr(basename(__FILE__), 0, -3)).'yaml';

        // キャッシュマネージャ
        $plugin =& $this->backend->getPlugin();
        $cache_manager =& $plugin->getPlugin('Cachemanager', 'Localfile');
        // キャッシュKeyの設定
        $cache_key = md5($yaml_path);
        // このKeyに対する有効なキャッシュの確認
        if ($cache_manager->isCached($cache_key)) { // キャッシュがヒット
            $this->form = $cache_manager->get($cache_key);
        } else { // 有効なキャッシュが見つからなかった
            $this->form = Spyc::YAMLLoad($yaml_path);
            // 省略値補正
            $constants = get_defined_constants();
            foreach ($this->form as $name => $value) {
                foreach ($this->def as $k) {
                    if (isset($value[$k]) == false) {
                        $this->form[$name][$k] = null;
                    }
                    // type, form_typeの補正
                    if (isset($value[$k]) && in_array($k, array('type', 'form_type'))
                            && array_key_exists($value[$k], $constants)) {
                        $this->form[$name][$k] = $constants[$value[$k]];
                    }
                }
            }
            // データをキャッシュする
            $cache_manager->set($cache_key, $this->form);
        }
    } 

カテゴリー: 日記 タグ:

PHPのyamlパーサ

2008 年 4 月 26 日 コメントはありません

PECL::syck
いつの間にかPECL入りしてた。
Cライブラリなので速度は速いがbetaだったり、windowsバイナリは配布されていなかったり、PECLコマンドでコンパイルできなかったり。

spyc
ピュアPHPなので遅い。
syckと挙動が異なったりする。

sfYaml
Symfony1.1系のライブラリ。
もともとはspycを利用していたが、自前で準備&syckの関数があったらそちらを使う。

sfYaml触ってみたけど、symfonyで利用する上で問題ないだけなレベルでyamlパーサとしてはまともに利用できませんでした。
ex.


True: true
# [1] => boole(true)
- name: yotsuba
  age: 14
# InvalidArgumentException
カテゴリー: 日記 タグ:

原因の切り分けをしっかりしましょう

2008 年 4 月 25 日 コメントはありません

PostgreSQLの7.4.Xの環境でDBをSQL_ASCII、PHPでclient_encodingをSJISで利用していたらリストアができないらしい。
実行環境はRedHat8系でした。


$ pg_dump backup | psql restore

確かにうまくいかない。


$ pg_dump backup > backup.dump

dumpファイル見てみると、先頭部分で「SET client_encoding = ‘EUC-JP’;」エラー発生した部分みてみるとデータの欠落がありました。
pg_dumpって特にエラーとか吐かないんですね。
リストアできないっていってたけど、問題はダンプがしっかりできないことっぽい。

ということでpg_dumpでクライアントエンコーディングを指定してあげることに。


$ export PGCLIENTENCODING=SJIS
$ pg_dump backup > backup.dump
$ psql restore < backup.dump

おゃできましたよ?

マイナー(リビジョン)バージョンでの差は知らん。

カテゴリー: 日記 タグ:

iモードID

2008 年 4 月 25 日 コメントはありません

絶望の世界そんなわけでiモードID調べてみた。

・SSLで利用できない
これは糞仕様。
utn使います。

・POSTでもリクエストラインに付与する
リクエストメソッドがPOSTでもPOSTでパラメータ渡しても取得できません。


ID:<?php print isset($_SERVER['HTTP_X_DCMGUID'])? $_SERVER['HTTP_X_DCMGUID']: '' <br />

<a href="<?php print $_SERVER['SCRIPT_NAME']; ?guid=on">GET</a>

<form action="<?php print $_SERVER['SCRIPT_NAME']; ?guid=on" method="POST">
<input type="submit" value="POST" />
</form>

<form action="<?php print $_SERVER['SCRIPT_NAME']; " method="POST">
<input type="hidden" name="guid" value="on" />
<input type="submit" value="POST2" />
</form> 

POST2からじゃ取得できない。
output_add_rewrite_varが使えません。
もともと使いませんが。

使いづらい仕様ですが、KDDIの垂れ流しよりはマシ。

iモードIDの話おしまい。

DoCoMoはクッキーが利用できないというのはよく知られていますが、リファラも利用できません。
アクセス解析やSEO的にはあいたたですが、リファからセッションIDが漏れることによるセッションハイジャックの心配がないのはすばらしい。
DoCoMoとSoftBankは公式サイト(公式メニューにリンクがあるサイト)独自のUID取得方法が存在しますが、KDDIのはどこでも垂れ流し。
まさかないとは思いますが、UserAgent偽装しただけでアクセスできる携帯サイトの場合、HTTPリクエストの際にUIDを付加してあげるだけで有料ページへアクセスできたりとか。
やばいよねー。
キャリアの公開してる接続IP帯域でチェックは必須です。
糞サイト側の問題ではありますが、KDDI端末を使う気にはなれません。

カテゴリー: 日記 タグ:

便利?

2008 年 4 月 25 日 コメントはありません

携帯向けXHTMLを出力する場合に便利なPHPのパッチ
実際このパッチをあてればOKと思う人が多そうで危険。
上記のパッチは、出力時内部エンコードからShift_JIS変換を利用する場合必要であり、そのようなphp.iniの設定が必要です。
スクリプトをEUC-JPで書いている場合のphp.iniの設定はこんな感じになるんじゃないでしょうか。


default_mimetype = application/xhtml+xml
output_handler = mb_output_handler
default_charset = Shift_JIS
mbstring.language = Japanese
mbstring.internal_encoding = eucJP-win
mbstring.encoding_translation = On
mbstring.http_input = auto
mbstring.http_output = SJIS-win
mbstring.detect_order = SJIS-win,UTF-8 

mb_output_handlerの説明みるとheader() で Content-Type が 設定されていない場合とあるので、後からContent-Typeを指定したらダメなのかな?
それだとすごく糞なきがしますがどうなんでしょ。

自分の場合はスクリプトファイルのエンコード、DBをShift_JISに統一する場合が圧倒的に多いです。
PHPに独自パッチを当てることの了承を得るよりも、上記のShift_JIS統一のより敷居が高い気がします。
PHPはコンパイルオプションに「–enable-zend-multibyte」をつけてコンパイルする(PHPと日本語)
DBは以下のように。
・MySQL ⇒ DB文字セットを「cp932」に設定(文字化けする場合はPHPとMySQLの個人的まとめ)
・PostgreSQL ⇒ DB文字セットを「UTF-8」か「EUC-JP」にし、接続毎に「pg_set_client_encofing(‘SJIS’);」を実行
・Oracle ⇒ DB文字セットをShift_JIS系に設定
・Sybase ⇒ DB文字セットをShift_JIS系に設定
php.iniの設定はだいぶスマートに。


default_charset = Shift_JIS
mbstring.language = Japanese
mbstring.internal_encoding = SJIS-win
mbstring.encoding_translation = Off
mbstring.http_input = pass
mbstring.http_output = pass 

カテゴリー: 日記 タグ:

JISとISO-2022-JPは違うんですって

2008 年 4 月 25 日 コメントはありません

mb_encode_mimeheaderは日本語なら「ISO-2022-JP」に変換する。


<?php
mb_language('ja');
mb_internal_encoding('SJIS-win');
$str = 'ァィゥェォ㈱';
echo mb_encode_mimeheader($str)."\n";
echo '=?ISO-2022-JP?B?'.base64_encode(mb_convert_encoding($str, 'ISO-2022-JP')).'?='."\n";
echo '=?ISO-2022-JP?B?'.base64_encode(mb_convert_encoding($str, 'JIS')).'?='."\n";

=?ISO-2022-JP?B?Pz8/Pz8/?=
=?ISO-2022-JP?B?Pz8/Pz8/?=
=?ISO-2022-JP?B?GyhJJygpKisbKEI/?= 

「ISO-2022-JP」と「JIS」とPHP5.1より利用できるようになった「ISO-2022-JP-MS」の違い。


<?php
mb_internal_encoding('SJIS-win');
header('Content-type: text/plain; charset=ISO-2022-JP');
echo mb_convert_encoding("ァィゥェォ㈱", 'ISO-2022-JP')."\n";
echo mb_convert_encoding("ァィゥェォ㈱", 'JIS')."\n";
echo mb_convert_encoding("ァィゥェォ㈱", 'ISO-2022-JP-MS')."\n";

??????
ァィゥェォ?
ァィゥェォ㈱ 

カテゴリー: 日記 タグ:

携帯端末のIPアドレス帯域

2008 年 4 月 25 日 コメントはありません

iモードID通知について(pdf)
DoCoMoもついにID通知サービス始めるらしい。

IPアドレス帯域制限用.htacces。

emobileは公式にみつからんかったので保留。


order deny,allow
deny from all

# DoCoMo
# http://www.nttdocomo.co.jp/service/imode/make/content/ip/
allow from 210.153.84.0/24
allow from 210.136.161.0/24
allow from 210.153.86.0/24

# au
# http://www.au.kddi.com/ezfactory/tec/spec/ezsava_ip.html
allow from 210.169.40.0/24
allow from 210.196.3.192/26
allow from 210.196.5.192/26
allow from 210.230.128.0/24
allow from 210.230.141.192/26
allow from 210.234.105.32/29
allow from 210.234.108.64/26
allow from 210.251.1.192/26
allow from 210.251.2.0/27
allow from 211.5.1.0/24
allow from 211.5.2.128/25
allow from 211.5.7.0/24
allow from 218.222.1.0/24
allow from 61.117.0.0/24
allow from 61.117.1.0/24
allow from 61.117.2.0/26
allow from 61.202.3.0/24
allow from 219.108.158.0/26
allow from 219.125.148.0/24
allow from 222.5.63.0/24
allow from 222.7.56.0/24
allow from 222.5.62.128/25
allow from 222.7.57.0/24
allow from 59.135.38.128/25
allow from 219.108.157.0/25
allow from 219.125.151.128/25
allow from 219.125.145.0/25
allow from 121.111.231.0/25
allow from 121.111.231.160/27
allow from 121.111.227.0/25

# SoftBank
# http://developers.softbankmobile.co.jp/dp/tech_svc/web/ip.php
allow from 123.108.236.0/24
allow from 123.108.237.0/27
allow from 202.179.204.0/24
allow from 202.253.96.224/27
allow from 210.146.7.192/26
allow from 210.146.60.192/26
allow from 210.151.9.128/26
allow from 210.169.130.112/28
allow from 210.175.1.128/25
allow from 210.228.189.0/24
allow from 211.8.159.128/25

# WILLCOM
# http://www.willcom-inc.com/ja/service/contents_service/club_air_edge/for_phone/ip/
allow from 61.198.142.0/24
allow from 219.108.14.0/24
allow from 61.198.161.0/24
allow from 219.108.0.0/24
allow from 61.198.249.0/24
allow from 219.108.1.0/24
allow from 61.198.250.0/24
allow from 219.108.2.0/24
allow from 61.198.253.0/24
allow from 219.108.3.0/24
allow from 61.198.254.0/24
allow from 219.108.4.0/24
allow from 61.198.255.0/24
allow from 219.108.5.0/24
allow from 61.204.3.0/25
allow from 219.108.6.0/24
allow from 61.204.4.0/24
allow from 221.119.0.0/24
allow from 61.204.6.0/25
allow from 221.119.1.0/24
allow from 125.28.4.0/24
allow from 221.119.2.0/24
allow from 125.28.5.0/24
allow from 221.119.3.0/24
allow from 125.28.6.0/24
allow from 221.119.4.0/24
allow from 125.28.7.0/24
allow from 221.119.5.0/24
allow from 125.28.8.0/24
allow from 221.119.6.0/24
allow from 211.18.235.0/24
allow from 221.119.7.0/24
allow from 211.18.238.0/24
allow from 221.119.8.0/24
allow from 211.18.239.0/24
allow from 221.119.9.0/24
allow from 125.28.11.0/24
allow from 125.28.13.0/24
allow from 125.28.12.0/24
allow from 125.28.14.0/24
allow from 125.28.2.0/24
allow from 125.28.3.0/24
allow from 211.18.232.0/24
allow from 211.18.233.0/24
allow from 211.18.236.0/24
allow from 211.18.237.0/24
allow from 125.28.0.0/24
allow from 125.28.1.0/24
allow from 61.204.0.0/24
allow from 210.168.246.0/24
allow from 210.168.247.0/24
allow from 219.108.7.0/24
allow from 61.204.2.0/24
allow from 61.204.5.0/24
allow from 61.198.129.0/24
allow from 61.198.140.0/24
allow from 61.198.141.0/24
allow from 125.28.15.0/24
allow from 61.198.165.0/24
allow from 61.198.166.0/24
allow from 61.198.168.0/24
allow from 61.198.169.0/24
allow from 61.198.170.0/24
allow from 61.198.248.0/24
allow from 125.28.16.0/24
allow from 125.28.17.0/24
allow from 211.18.234.0/24
allow from 219.108.8.0/24
allow from 219.108.9.0/24
allow from 219.108.10.0/24
allow from 61.198.138.100/32
allow from 61.198.138.101/32
allow from 61.198.138.102/32
allow from 61.198.139.160/28
allow from 61.198.139.128/27
allow from 61.198.138.103/32
allow from 61.198.139.0/29
allow from 219.108.15.0/24
allow from 61.198.130.0/24
allow from 61.198.163.0/24
allow from 61.204.6.128/25
allow from 61.204.7.0/25
allow from 61.204.92.0/24
allow from 61.204.93.0/24
allow from 61.204.94.0/24
allow from 61.204.95.0/24
allow from 61.198.128.0/24
allow from 61.198.131.0/24
allow from 61.198.143.0/24
allow from 61.198.172.0/24
allow from 61.198.173.0/24
allow from 61.198.252.0/24
allow from 61.204.3.128/25
allow from 211.126.192.128/25

# emobile
カテゴリー: 日記 タグ: