home ホーム search 検索 -  login ログイン  | help ヘルプ

find 検索

1291 - 1300 / 1320    [|<]  [|<]  [<]  121  122  123  124  125  126  127  128  129  130   [>]  [>|][>|]
タイトル/名前 更新者 更新日
PHP/HTML_QuickFormメモ/20050601/addRuleの引数のハック msakamoto-sf 2008-12-21 22:17:24
PHP/HTML_QuickFormメモ/20050601/裏技その1 msakamoto-sf 2008-12-21 22:11:55
PHP/ADODB/セッションデータの暗号化メモ msakamoto-sf 2008-12-21 22:07:49
PHP/xdebugメモ msakamoto-sf 2008-12-21 21:52:33
PHP/Smartyメモ msakamoto-sf 2008-12-21 21:37:40
PHP/PEARインストールメモ msakamoto-sf 2008-12-21 21:12:16
PHP/第38回PHP勉強会資料 msakamoto-sf 2008-12-21 00:01:03
PHP/セッションとクッキーの共存 msakamoto-sf 2008-12-16 08:16:21
添付ファイル/PHP/cookie-sessions.zip msakamoto-sf 2008-12-16 08:13:27
PHP/ADODB/アンダースコア("_")を含むDB名で嵌った件 msakamoto-sf 2008-12-16 08:04:31
ソート項目 / ソート順     1ページ 件ずつ表示

PHP/HTML_QuickFormメモ/20050601/addRuleの引数のハック  

所有者: msakamoto-sf    作成日: 2005-06-01 22:12:12
カテゴリ: PHP 

HTML_QuickForm::addRule()の引数で一部不明なのがありましたので、ちょっとハックしてみました。

形式 :

void addRule(
    string $element, 
    string $message, 
    string $type, 
   [string $format = null], 
   [string $validation = 'server'], 
   [boolean $reset = false], 
   [boolean $force = false])

中身:

string $element Form element name
string $message Message to display for invalid data
string $type Rule type, use getRegisteredRules() to get types
string $format (optional)Required for extra rule data
string $validation (optional)Where to perform validation: "server", "client"
boolean $reset Client-side validation: reset the form element
to its original value if there is an error?
boolean $force Force the rule to be applied,
even if the target form element does not exist

$element, $message, $type, $validation, $reset, $forceまでは、まあ、英語の解説でわかるんですよ。
問題は $format 引数。

HTML_QuickForm::addRule()をハックしてみると、

$this->_rules[$element][] = array(
    'type'        => $type,
    'format'      => $format,
    'message'     => $message,
    'validation'  => $validation,
    'reset'       => $reset,
    'dependent'   => $dependent
    );

みたくなってて、内部の$_rules[]に連想配列でセットされてます。んで、これが使われているところはメインはHTML_QuickForm::validate()なのでちょっと調べてみます。

function validate() {
    ...
    $registry =& HTML_QuickForm_RuleRegistry::singleton();
    ...
    $result = $registry->validate(
        $rule['type'], 
        $submitValue, 
        $rule['format'], ...);

のように使われてました*1
結構後の方まで引きずってます。んで、HTML_QuickForm_RuleRegistryというのは、結局Ruleの統合インターフェイスですな。シングルトンですから、ぶっちゃけファクトリーみたいなもんです。中身は。
んで、それのvalidateを調べてみます。

function validate($ruleName, $values, $options = null, $multiple = false) {
   ...
   $rule =& $this->getRule($ruleName);
   ...
   return $rule->validate($values, $options);
}
HTML_QuickForm::validate() HTML_QuickForm_RuleRegistry::validate()
$rule['type'] $ruleName
$submitValue $values
$rule['format'] $options
*2 $multiple

えーっとですね・・・ちょっと疲れてきましたが。
getRuleっつーのはあれですな、Validation系クラスのFactroyデザインパターンのインターフェイスです。ですから結局のところ、Rule/ディレクトリ以下の各クラスのvalidate()メソッドが呼び出されるわけです。最終的に・・・

HTML_QuickForm HTML_QuickForm_RuleRegistry 各Ruleクラス
$submitValue $values*3 $value
$format $options $option

みたく受け渡されていきます。 ・・・$formatという引数名、おかしくない?・・・
素直に$optionsとか、$rule_paramsとかつけてくれてればもうちょっとわかりやすいのに。

ちなみに、HTML_QuickFormのパッケージではRule/以下は次のファイルしかありません。

  • Callback.php
  • Compare.php
  • Email.php
  • Range.php
  • Regex.php
  • Required.php

このうち、少なくともCallback.phpとRegex.phpで$optionが、ひいては$format引数が使用されています。たとえばCallback.phpでしたら、コールバック関数(call_user_func)に唯一PHPスクリプトからプログラマーが渡せる引数として利用されていますし、Regex.phpでは同様で、内部で分岐こそしていますが、基本的にはpreg_matchに渡す正規表現として使用されています。


*1: ちなみにformatの後の...は、$rules['howmany']がセットされていればtrue, いなければfalseで、これはHTML_QuickForm_RuleRegistryのvalidate()のmultipleに影響します。
*2: is_array($submitValue) && !isset($rule['howmany'])の場合true, でなければfalse
*3: 配列の場合はforeachで分解される

プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2008-12-21 22:17:24
md5:c19e7ed56a8418a574361e6064840325
sha1:6ca77da751e09c0d92ef8a47a4055955baae8f02

PHP/HTML_QuickFormメモ/20050601/裏技その1  

所有者: msakamoto-sf    作成日: 2005-06-01 22:10:33
カテゴリ: PHP 

$form->addElement('text', 'name', array(
	'imgタグのalt属性',
	'label' => 'カスタム要素',
	'label2' => 'カスタム要素2'
	));

こうすると、少なくともSmartyArrayレンダラを使った場合、

$form.name.label => 'imgタグのalt属性',
$form.name.label_label => 'カスタム要素',
$form.name.label_label2 => 'カスタム要素2'

みたく、自動的にlabel要素に + _(キー名)みたいな形で生成される裏技。



プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2008-12-21 22:11:55
md5:c22f2ff5c386f1f36a74c4467e786349
sha1:41706cbc68f1f581dcd7cb1e15742e50a806ab80

PHP/ADODB/セッションデータの暗号化メモ  

所有者: msakamoto-sf    作成日: 2005-06-15 21:57:24
カテゴリ: PHP 

2005年6月前後、ADODBを使ってセッション情報をDBに保持させるアプリを作っていた時のメモ。一応2008年12月時点のADODBドキュメントに合わせてアップデートしました。

ADODBではセッションデータをDBに保存する為のサポートハンドラが提供されていて、生データではなくて暗号化して保存する事も可能になっている。
http://phplens.com/lens/adodb/docs-session.htm
を参照すると、

MD5Crypt (crypt.inc.php)
MCrypt
Secure (Horde's emulation of MCrypt, if MCrypt module is not available.)
GZip
BZip2

のように何種類かEncrypt/Decryptできるようになっている。
MCryptについてはPHPのエクステンションで提供される為、PHPマニュアルなどを参照してプラットフォームに合わせてライブラリやPHPのコンパイルオプションを調整する必要がある。

この辺、2005年6月前後ではMCryptのエミュレーションを使っていて、それが1500ms位食っててボトルネックになっていた。2005年当時は「じゃぁMCrypt止めよう、どうせ開発環境だし。」とスッパリ諦めていた。
様々な環境が簡単に整えられるようになった2008年現在は、多少無理してでもちゃんとMCryptの拡張を入れた方が良いのかも知れない。(DBとファイルに加え、memcachedという選択肢も出来たわけだし色々かも。)



プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2008-12-21 22:07:49
md5:ecb93738f3af884475e80996e21a95d3
sha1:ef3144d9284e7d1df948464fe7e48cff32c46512

PHP/xdebugメモ  

所有者: msakamoto-sf    作成日: 2005-06-15 21:46:19
カテゴリ: PHP 

最後のアップデートが2005年6月前後のxdebugのメモ。PHP4がまだ現役だった頃ですが、既にxdebugは有名だった気がします。


環境(OSはWinXP+SP2)

PHP-4.3.11 c:\php\
php.ini c:\windows\php.ini
extension_dir c:\php\extensions\
Apache2 c:\program files\apache group\apache2

xdebugの導入

http://www.xdebug.org/

ダウンロードできます。ただ、Linux版の最新は結構他にも転がってるっぽいんですが(PECL?)、Windows版のバイナリDLLは上記URLの「BINARY SNAPSHOTS (2.0dev)」とかいうとこから落とします。

落としたDLLファイルを、PHPのextension_dirに指定してあるディレクトリにコピー。その後、php.iniに以下の行を付け足します。

extension=...
...
extension=xdebug-4.3.6-2.0.0beta1.dll(バージョン部分とかは多少前後有り)

これでApacheを再起動し、phpinfo()を呼び出して xdebug の項目が表示されれば動作完了です。

xdebugでprofiling

詳細は下記公式ドキュメント参照。
http://www.xdebug.org/docs/

とりあえず、まずはプロファイル出力ディレクトリを用意しておきます。今回はc:\php\xdebug.profilesというフォルダを作りました。んで、profilingしたいPHPアプリのトップにいつものごとく.htaccessファイルを作って、次のように書いておきます。

php_flag xdebug.profiler_enable on
php_value xdebug.profiler_output_dir "C:\php\xdebug.profiles"

php.iniに書いて全体に適用*1したい場合はphp.iniに、extensionの指定後、

xdebug.profiler_enable = on
xdebug.profiler_output_dir "C:\php\xdebug.profiles"

の用に指定しておきます。

さて、こうすると.htaccess配下のPHPファイルの挙動は全てprofilingされだします。
んで、出力されたプロファイルを解析するツールが必要になるわけです。
公式ドキュメントサイトでも言及されていますが、 CacheGrind というたぐいのツールが使えるそうです。KDE用のKCacheGrindとWindows用のWinCacheGrindがあるそうです。KDEもWindowsも使いたくない場合はPerlScriptでテキストに落とし込むのも一応あるにはあるそうですが。

今回はWindows上で動かしてるので、当然WinCacheGrindというのを使います。
http://sourceforge.net/projects/wincachegrind

WinCacheGrindにプロファイルログを読み込ませると、関数の呼び出し順序や回数、時間などが分かりやすく確認できるのでお奨めです。


*1: プロファイル出力ファイルのサイズはかなり大きいので、全体に適用するのはおすすめできない

プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2008-12-21 21:52:33
md5:f89ec8bc80fed83cde4393121cb95033
sha1:a858f89428a2bbb070d0e666ec76b90744c7a05c

PHP/Smartyメモ  

所有者: msakamoto-sf    作成日: 2005-06-15 21:22:14
カテゴリ: PHP 

高機能なPHPテンプレートHTMLエンジン、Smartyについての2005年6月当時のメモです。当時はバージョンが2.6.6とかその辺を使ってました。2008年12月現在、大分マイナーバージョンが上がっていますが、基本的な使い方やセキュリティ面でのTipsは今でも役に立つと思います。

公式サイト: http://www.smarty.net/
公式日本語マニュアル: http://www.smarty.net/manual/ja/


インストールやマニュアル、使い方

公式日本語マニュアル参照: http://www.smarty.net/manual/ja/

実際の使い方のノウハウは、Smartyを使っているCMSアプリのコードを調べてみることをお奨めします。自分もXOOPSのコードで色々勉強しました。*1

また

Smarty-2.6.x/demo/

以下にサンプルが入っていますので、そちらも忘れずに目を通してみましょう。

LinuxやUNIXユーザの場合、templates_cディレクトリをWebサーバ実行ユーザーから書き込み可能にしておくのを忘れずに。

$ chmod 777 templates_c/

とでも実行しておいてください。

Tips, ノウハウ, ハウツー

Smartyのタグをデフォルトの"{"から変更するには

Smartyのコマンドタグは、"{"で始まり"}"で終わるのがデフォルトです。しかし、これだとJavaScriptの関数と同じなので、不便です。

そこで、XOOPSやYakiBikiでは次のようにして、"<{"と"}>"に変更しています。

$smarty = new Smarty;
$smarty->left_delimiter = "<{";
$smarty->right_delimiter = "}>";

テンプレートHTMLをデータベースから読み出すには

XOOPSのコードを見てみましょう。

xoops-2.X.X/html/class/smarty/plugins/resource.db.php

上記ファイルが参考になるはずです。

(2005年当時のファイルになります。2008年現在、XoopsCubeになってどうなっているのかは分かりません、御免なさい。)

セキュリティ上の問題

データベースを利用して、テンプレートをユーザーが自由に変更できるようなCMSを作成する場合、絶対に注意しなければならない事項があります。

Smartyのデフォルトでは {php} - {/php} 組み込み関数により、自由にPHPコードを記述できます。 これはすなわちユーザーに、PHPでできるありとあらゆる操作を行える力を与えることに他なりません。

JavaScriptを埋め込まれる以上に危険なこの機能を無効化するには、 $securityプロパティをtrueにします。

$smarty->security = true;

この一行を絶対に忘れないでください。

この場合でもし{php}タグが使われていた場合、Smartyはエラーを出力すると同時に処理も続行します。

オブジェクトを割り当てる場合のプライベート("_"で始まる)要素への制限

ここも2005年当時の話です。アップデートできず御免なさい。2008年現在は、公式日本語マニュアルの「第15章 拡張機能」→「オブジェクト」の項を参照して下さい。

オブジェクトを割り当てる場合、

register_object
assign(_by_ref)

の二種類が存在します。

register_objectを使うと、第三パラメータに使用可能なメソッド・メンバ名を配列で指示できます。

assign(_by_ref)では、以下の二つの条件すべてが成立している場合に、"_"で始まるメンバ・メソッドへの(テンプレートHTML内での)アクセスを禁止できます。(Smarty errorが発生します。)

  • assign(_by_ref)で割り当てている。
  • $smarty->security = true にしている。

register_object()に関しては、この"_"で始まる要素へのアクセス制限機能は適用されないことに注意してください。

このオブジェクト割り当てを調べたときの過程をメモっておきます。

Smarty.class.php

まず、register_object でSmartyのソースツリー(正確にはlibs/以下)をgrepしました。そしたら、Smarty.class.phpの

function register_object($object, &$object_impl, 
    $allowed = array(), $smarty_args = true, $block_methods = array())
{
    settype($allowed, 'array');
    settype($smarty_args, 'boolean');
    $this->_reg_objects[$object] =
        array(&$object_impl, $allowed, $smarty_args, $block_methods);
}

にヒットしました。んで、これ見ると_reg_objects[]という配列にいろいろセットされてます。実際にregister_objectで割り当てたオブジェクトを使用しているテンプレートHTMLのコンパイル後の該当部分を見てみると、

<{obj1->meth1 ... }>

が、

<?php echo $this->_reg_objects['obj1'][0]->meth1(array(), $this);?>

になってました。

Smarty_Compiler.class.php

先の調査結果をふまえて、_reg_objectsでgrepしたら、Smarty_Compiler.class.php中で

function _compile_registered_object_tag($tag_command, $attrs, $tag_modifier)

が見つかりました。んで、調べていくと・・・

} elseif(
    !empty($this->_reg_objects[$object][1]) && 
    !in_array($obj_comp, $this->_reg_objects[$object][1])) {
    $this->_trigger_fatal_error(
        "'$obj_comp' is not a registered component of object '$object'",
        $this->_current_file, 
        $this->_current_line_no, __FILE__, __LINE__);

というのが見つかりました。$obj_compというのはこの関数の前の方で

list($object, $obj_comp) = explode('->', $tag_command);

として取得されています。つまりメンバ・メソッド名の部分ですな。

というわけで、register_object()の場合は $smarty->securityとは何の関係もないどころか、"_"ではじまるプライベート要素にはアクセスし放題というわけです。
だから代わりに、register_object()の第三パラメータの配列でアクセス制限をかけている訳ですね。(代わりというわけではないと思いますが。)

結局"_"で始まるアクセス制限はどうしてるのか?

'_'でSmarty_Compiler.class.phpを検索したら見つかりました。_parse_varとかいう関数の中で、

} else if (substr($_index,0,2) == '->') {
    if(substr($_index,2,2) == '__') {
        $this->_syntax_error(
            'call to internal object members is not allowed', 
            E_USER_ERROR, __FILE__, __LINE__);
    } elseif($this->security && substr($_index, 2, 1) == '_') {
        $this->_syntax_error(
            '(secure) call to private object member is not allowed', 
            E_USER_ERROR, __FILE__, __LINE__);

みたくなってました。


*1: XOOPSの場合はDBからテンプレートリソースを読み出す機能があり、resourceプラグインの作り方はこれを見て勉強しました。

プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2008-12-21 21:37:40
md5:c5c7f32e38d4aee4666e5d6f429d3974
sha1:97d08c7b1b7780e8eeb4552eb5ce04578f59ba23

PHP/PEARインストールメモ  

所有者: msakamoto-sf    作成日: 2007-09-11 21:08:00
カテゴリ: PHP 

とあるライブラリをPEARにまとめようと思った。
ついでに、ローカル(Windows)の環境もPHP5にしようと思った。
で、最初はCGI形式にしてPHP4とPHP5の両方を動かせるようにすればいいや、と思っていろいろApacheの設定弄くったけど、上手く行かなくて挫折。

で、素直にPHP5を入れた後、PEARをきっちりとインストールしてみようと思った。
というのは、phpDocumentor等を入れると、何故か

c:\php4

というディレクトリが勝手に作られてしまう。これが非常に邪魔だったので、なんとしてもこの問題をクリアしたかった。


何処に入れるか。

個人的な環境では、以下のようにセッティングし、"pear_0"ディレクトリにインストールしようと目論んでいる。go-pear.batや、go-pear.pharは、PHP5に添付のファイルをコピー。

C:\in_vitro\
            apps\
                 php4\ ... PHP4。PHPUnitとかで動かすかもしんない。
                 php5\ ... PHP5。
                 pear_0\ ... PEAR。とりあえず普通に使うものと言う意味で、"_0"。
                        go-pear.bat
                        PEAR\go-pear.phar

go-pear.batの実行

その前に、go-pear.batを若干修正しておく。

@ECHO OFF
set PHP_BIN=C:\in_vitro\apps\php5\php.exe
%PHP_BIN% -d output_buffering=0 C:\in_vitro\apps\pear_0\PEAR\go-pear.phar
pause

間違えてPHP4のバイナリを動かさないよう、PHP_BINをフルパスで指定。あと、これも間違ってPHP5に入っているPEARではなく、ちゃんと今回セッティングしたpear_0を見に行くようフルパスで指定。

で、動かす。

> cd c:\in_vitro\apps\pear_0
C:\in_vitro\apps\pear_0> go-pear.bat

Are you installing a system-wide PEAR or a local copy?
(system|local) [system] :(そのままENTER)

Below is a suggested file layout for your new PEAR installation.  To
change individual locations, type the number in front of the
directory.  Type 'all' to change all of them or simply press Enter to
accept these locations.

 1. Installation base ($prefix)        : C:\in_vitro\apps\pear_0
 2. Temporary directory for processing : C:\in_vitro\apps\pear_0\tmp
 3. Temporary directory for downloads  : C:\in_vitro\apps\pear_0\tmp
 4. Binaries directory                 : C:\in_vitro\apps\pear_0
 5. PHP code directory ($php_dir)      : C:\in_vitro\apps\pear_0\pear
 6. Documentation directory            : C:\in_vitro\apps\pear_0\pear\docs
 7. Data directory                     : C:\in_vitro\apps\pear_0\pear\data
 8. Tests directory                    : C:\in_vitro\apps\pear_0\pear\tests
 9. Name of configuration file         : C:\WINDOWS\pear.ini
10. Path to CLI php.exe                : C:\in_vitro\apps\php5
1-10, 'all' or Enter to continue: all

ここで、PEARディレクトリ内には純粋にライブラリとしてのPHPファイルしか入れたく無かった為、6, 7, 8を修正。あと、2と3が一緒なのもアレなので、3を修正。あと、9も修正した。後で顧みるに、9については結局意味が無かったようだけど・・・。

Installation base ($prefix) [C:\in_vitro\apps\pear_0] :
Temporary directory for processing [$prefix\tmp] :
Temporary directory for downloads [$prefix\tmp] : $prefix\downloads
Binaries directory [$prefix] : $prefix\bin
PHP code directory ($php_dir) [$prefix\pear] :
Documentation directory [$php_dir\docs] : $prefix\docs
Data directory [$php_dir\data] : $prefix\data
Tests directory [$php_dir\tests] : $prefix\tests
Name of configuration file [C:\WINDOWS\pear.ini] : $prefix\pear_0_system.ini
Path to CLI php.exe [C:\in_vitro\apps\php5] :

Below is a suggested file layout for your new PEAR installation.  To
change individual locations, type the number in front of the
directory.  Type 'all' to change all of them or simply press Enter to
accept these locations.

 1. Installation base ($prefix)        : C:\in_vitro\apps\pear_0
 2. Temporary directory for processing : C:\in_vitro\apps\pear_0\tmp
 3. Temporary directory for downloads  : C:\in_vitro\apps\pear_0\downloads
 4. Binaries directory                 : C:\in_vitro\apps\pear_0\bin
 5. PHP code directory ($php_dir)      : C:\in_vitro\apps\pear_0\pear
 6. Documentation directory            : C:\in_vitro\apps\pear_0\docs
 7. Data directory                     : C:\in_vitro\apps\pear_0\data
 8. Tests directory                    : C:\in_vitro\apps\pear_0\tests
 9. Name of configuration file         : C:\in_vitro\apps\pear_0\pear_0_system.ini
10. Path to CLI php.exe                : C:\in_vitro\apps\php5

1-10, 'all' or Enter to continue: (ContinueなのでENTER)

...

** WARNING! Old version found at C:\in_vitro\apps\pear_0\bin, please remove it or be sure 
to use the new c:\in_vitro\apps\pear_0\bin\pear.bat command

The 'pear' command is now at your service at c:\in_vitro\apps\pear_0\bin\pear.bat

** The 'pear' command is not currently in your PATH, so you need to
** use 'c:\in_vitro\apps\pear_0\bin\pear.bat' until you have added
** 'C:\in_vitro\apps\pear_0\bin' to your PATH environment variable.

Run it without parameters to see the available actions, try 'pear list'
to see what packages are installed, or 'pear help' for help.

For more information about PEAR, see:

  http://pear.php.net/faq.php
  http://pear.php.net/manual/

Thanks for using go-pear!

これで、pear.batが

c:\in_vitro\apps\pear_0\bin\pear.bat

としてインストールされた。実際にrequireされるライブラリなどは、

c:\in_vitro\apps\pear_0\PEAR

配下になり、こちらは既にphp.iniのinclude_pathに追加済。

で、今回PHP5に入れ替えたのもあるため、いつもの環境設定バッチファイルを修正する。

c:\in_vitro\setenv.bat


REM PHP5
set PHP5_HOME=C:\in_vitro\apps\php5

REM PEAR_0
set PEAR_0_HOME=C:\in_vitro\apps\pear_0\bin

...

set PATH=...;%PHP5_HOME%;%PEAR_0_HOME%;...

ここら辺は大体こんな感じで、細かくはお好みでいつも手を抜いたり凝ったりしている箇所。

次が本題。

PEARの設定の上手い保存方法について

最初、go-pear.batの実行時。

 9. Name of configuration file         : C:\in_vitro\apps\pear_0\pear_0_system.ini

これを設定していた為、てっきりここに保存されるものだと・・・思っていた自分が阿呆でした。

ファイルは作られたのですが、普通に

> pear install pear/PhpDocumentor

とかすると、何故か

c:\php5\pear\data
             docs

とかできちゃうんですよねぇ~~~~。

C:\in_vitro>pear config-show
CONFIGURATION (CHANNEL PEAR.PHP.NET):
=====================================
Auto-discover new Channels     auto_discover    <not set>
Default Channel                default_channel  pear.php.net
HTTP Proxy Server Address      http_proxy       <not set>
PEAR server [DEPRECATED]       master_server    pear.php.net
Default Channel Mirror         preferred_mirror pear.php.net
Remote Configuration File      remote_config    <not set>
PEAR executables directory     bin_dir          C:\in_vitro\apps\pear_0\bin
PEAR documentation directory   doc_dir          C:\php5\pear\docs
PHP extension directory        ext_dir          C:\in_vitro\apps\php5\ext
PEAR directory                 php_dir          C:\in_vitro\apps\pear_0\pear
PEAR Installer cache directory cache_dir        C:\DOCUME~1\FengJing\LOCALS~1\Temp\pear\cache
PEAR data directory            data_dir         C:\php5\pear\data
PEAR Installer download        download_dir     C:\DOCUME~1\FengJing\LOCALS~1\Temp\pear\cache
directory
PHP CLI/CGI binary             php_bin          C:\in_vitro\apps\php5\php.exe
php.ini location               php_ini          <not set>
PEAR Installer temp directory  temp_dir         C:\DOCUME~1\FengJing\LOCALS~1\Temp\pear\temp
PEAR test directory            test_dir         C:\php5\pear\tests
Cache TimeToLive               cache_ttl        3600
Preferred Package State        preferred_state  stable
Unix file mask                 umask            0
Debug Log Level                verbose          1
PEAR password (for             password         <not set>
maintainers)
Signature Handling Program     sig_bin          c:\gnupg\gpg.exe
Signature Key Directory        sig_keydir       C:\WINDOWS\pearkeys
Signature Key Id               sig_keyid        <not set>
Package Signature Type         sig_type         gpg
PEAR username (for             username         <not set>
maintainers)
User Configuration File        Filename         C:\WINDOWS\pear.ini
System Configuration File      Filename         C:\WINDOWS\pearsys.ini

うぉ~~~い、Configuration Fileも知らない間に C:\WINDOWS になってるしぃ~~~!?

で、この状態で

> pear config-set test_dir c:\in_vitro\apps\pear_0\tests

とかすると、

C:\WINDOWS\pear.ini

に設定が書き込まれちゃうんですよ!!!!

違うの違うの違うの~~~~~!!!そっちじゃねぇ~~~~!!!

結論:PHP_PEAR_SYSCONF_DIR 環境変数を設定せよ。

なんでかは置いておきまして、答えを先に。

> set PHP_PEAR_SYSCONF_DIR=c:\in_vitro\apps\pear_0

という感じで、 pear.iniを配置するディレクトリを、PHP_PEAR_SYSCONF_DIR環境変数に設定しておく 事により、まず、Configuration Fileの位置が指定されます。

C:\in_vitro>set PHP_PEAR_SYSCONF_DIR=c:\in_vitro\apps\pear_0
C:\in_vitro>pear config-show
CONFIGURATION (CHANNEL PEAR.PHP.NET):
=====================================
Auto-discover new Channels     auto_discover    <not set>
...
User Configuration File        Filename         c:\in_vitro\apps\pear_0\pear.ini
System Configuration File      Filename         c:\in_vitro\apps\pear_0\pearsys.ini

で、この状態で config-set を行うことで、今回の例であれば c:\in_vitro\apps\pear_0 の pear.ini と pearsys.ini に設定が書き込まれます。*1

ハイ、というわけで今回の完了状態:

> C:\in_vitro>pear config-show
CONFIGURATION (CHANNEL PEAR.PHP.NET):
=====================================
Auto-discover new Channels     auto_discover    <not set>
Default Channel                default_channel  pear.php.net
HTTP Proxy Server Address      http_proxy       <not set>
PEAR server [DEPRECATED]       master_server    pear.php.net
Default Channel Mirror         preferred_mirror pear.php.net
Remote Configuration File      remote_config    <not set>
PEAR executables directory     bin_dir          C:\in_vitro\apps\pear_0\bin
PEAR documentation directory   doc_dir          C:\in_vitro\apps\pear_0\docs
PHP extension directory        ext_dir          C:\in_vitro\apps\php5\ext
PEAR directory                 php_dir          C:\in_vitro\apps\pear_0\pear
PEAR Installer cache directory cache_dir        c:\in_vitro\apps\pear_0\cache
PEAR data directory            data_dir         C:\in_vitro\apps\pear_0\data
PEAR Installer download        download_dir     C:\in_vitro\apps\pear_0\downloads
directory
PHP CLI/CGI binary             php_bin          C:\in_vitro\apps\php5\php.exe
php.ini location               php_ini          c:\in_vitro\apps\php5\php.ini
PEAR Installer temp directory  temp_dir         C:\in_vitro\apps\pear_0\tmp
PEAR test directory            test_dir         C:\in_vitro\apps\pear_0\tests
Cache TimeToLive               cache_ttl        3600
Preferred Package State        preferred_state  stable
Unix file mask                 umask            0
Debug Log Level                verbose          1
PEAR password (for             password         <not set>
maintainers)
Signature Handling Program     sig_bin          c:\gnupg\gpg.exe
Signature Key Directory        sig_keydir       c:\in_vitro\apps\pear_0\pearkeys
Signature Key Id               sig_keyid        <not set>
Package Signature Type         sig_type         gpg
PEAR username (for             username         <not set>
maintainers)
User Configuration File        Filename         c:\in_vitro\apps\pear_0\pear.ini
System Configuration File      Filename         c:\in_vitro\apps\pear_0\pearsys.ini

種明かしと PEAR/Config.php の解説

PEARの設定値の秘密は、PEAR/Config.php ファイルにあります。
まず、今回関係してくる部分に注目し、PEAR/Config.php ファイルの構造を大雑把にまとめると以下のようになります。

  • デフォルト値用を含めた定数定義部
if (getenv('PHP_PEAR_SYSCONF_DIR')) {
    define('PEAR_CONFIG_SYSCONFDIR', getenv('PHP_PEAR_SYSCONF_DIR'));
} elseif (getenv('SystemRoot')) {
    define('PEAR_CONFIG_SYSCONFDIR', getenv('SystemRoot'));
} else {
    define('PEAR_CONFIG_SYSCONFDIR', PHP_SYSCONFDIR);
}

// Default for master_server
if (getenv('PHP_PEAR_MASTER_SERVER')) {
    define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', getenv('PHP_PEAR_MASTER_SERVER'));
} else {
    define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', 'pear.php.net');
}
...
  • PEAR_Config クラス定義
class PEAR_Config extends PEAR
    • 設定値の定義(上のデフォルト値はここで使われる)
   var $configuration_info = array(
       // Channels/Internet Access
       'default_channel' => array(
           'type' => 'string',
           'default' => PEAR_CONFIG_DEFAULT_CHANNEL,
           'doc' => 'the default channel to use for all non explicit commands',
           'prompt' => 'Default Channel',
           'group' => 'Internet Access',
           ),
       'preferred_mirror' => array(
           'type' => 'string',
           'default' => PEAR_CONFIG_DEFAULT_CHANNEL,
           'doc' => 'the default server or mirror to use for channel actions',
           'prompt' => 'Default Channel Mirror',
           'group' => 'Internet Access',
           ),
...
    • コンストラクタ
function PEAR_Config($user_file = '', $system_file = '', $ftp_file = false, 
$strict = true) { ...

Config.phpの冒頭では大量のdefine文が出てきますが、その殆どが、設定値のデフォルト値です。$configuration_infoに指定されています。逆に言えばそれ以外の定数値は、別の用途になりますが、今回の調査対象外ですのでスルーします。

で、なんで

c:\php4\pear

とか

c:\php5\pear

とか作られちゃうの?ですが、デフォルト値でそうした値になっている箇所を追っていくと正体が掴めます。例えばdataやtestsを見てみましょう。

'data_dir' => array(
    'type' => 'directory',
    'default' => PEAR_CONFIG_DEFAULT_DATA_DIR,
    ...
'test_dir' => array(
    'type' => 'directory',
    'default' => PEAR_CONFIG_DEFAULT_TEST_DIR,
    ...

→(getenvのブロックは除去して抽出)

define('PEAR_CONFIG_DEFAULT_DATA_DIR', $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'data');
define('PEAR_CONFIG_DEFAULT_TEST_DIR', $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'tests');

で、$PEAR_INSTALL_DIR は何なのかを見ていくと、Config.phpの冒頭で

if (!defined('PEAR_INSTALL_DIR') || !PEAR_INSTALL_DIR) {
    $PEAR_INSTALL_DIR = PHP_LIBDIR . DIRECTORY_SEPARATOR . 'pear';
} else {
    $PEAR_INSTALL_DIR = PEAR_INSTALL_DIR;
}

とあります。
もちろん、PEAR_INSTALL_DIR等という定数は定義せずに使用していますので、上の分岐に入ります。すると、PHP_LIBDIRという定数に"\pear"を付け足したものが$PEAR_INSTALL_DIRになることが分かりました。というわけで、

> php -r "echo PHP_LIBDIR;"
C:\php5

これで、

C:\php5 + "\pear" => c:\php5\pear

になり、この下にdataやらdocsやらtestsが作られる、と言うわけです。

さて、肝心の設定ファイルの位置ですが、コンストラクタにその部分が書かれています。

function PEAR_Config($user_file = '', $system_file = '', $ftp_file = false,
                     $strict = true)
{
    $this->PEAR();
    PEAR_Installer_Role::initializeConfig($this);
    $sl = DIRECTORY_SEPARATOR;
    if (empty($user_file)) {
        if (OS_WINDOWS) {
            $user_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini';
        } else {
            $user_file = getenv('HOME') . $sl . '.pearrc';
        }
    }
    if (empty($system_file)) {
        if (OS_WINDOWS) {
            $system_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pearsys.ini';
        } else {
            $system_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.conf';
        }
    }

UNIX系の場合はさておきまして(見れば同じ文脈でどうなるか、分かると思います。)、WINDOWSの場合は

$user_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini';
$system_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pearsys.ini';

となるようです。では、PEAR_CONFIG_SYSCONFDIR の定義を追ってみると・・・

if (getenv('PHP_PEAR_SYSCONF_DIR')) {
    define('PEAR_CONFIG_SYSCONFDIR', getenv('PHP_PEAR_SYSCONF_DIR'));
} elseif (getenv('SystemRoot')) {
    define('PEAR_CONFIG_SYSCONFDIR', getenv('SystemRoot'));
} else {
    define('PEAR_CONFIG_SYSCONFDIR', PHP_SYSCONFDIR);
}

とあります。次の優先順位で PEAR_CONFIG_SYSCONFDIR の値を設定していることが分かります。

  • PHP_PEAR_SYSCONF_DIR 環境変数
  • SystemRoot 環境変数
  • PHP_SYSCONFDIR 組込定数

ここから、PHP_PEAR_SYSCONF_DIR環境変数を設定することで、好みの場所のPEAR設定ファイルを参照することができる、と分かりました。

ちなみに、Windows版のPHP5では残り二つがどうなるかというと・・・

> php -r "echo getenv('SystemRoot');"
C:\WINDOWS
> php -r "echo PHP_SYSCONFDIR;"
C:\php5

と言う形になり、デフォルトで

C:\WINDOWS\pear.ini

になるのも納得できました。


*1: この二つ、どう違うのかは未調査。いつか、リベンジ。

プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2008-12-21 21:12:16
md5:5452c45271edf15239aaad94872cdb98
sha1:133c9dbb19b87bc5efa23405e71f7bae1fe31838

PHP/第38回PHP勉強会資料  

所有者: msakamoto-sf    作成日: 2008-12-20 23:50:43
カテゴリ: PHP 

第38回PHP勉強会で、殆どPHPが出てこない発表をして参りました。その時の資料です。

下記は発表の時に動かして見せたコードです。何の説明も無しに話を進めてしまったのは不味かったかなと反省してます。

多分IEの裏側を覗いてAPIレベルの挙動を確認したり、showModalDialog()というIEオンリーなJavaScriptを使用するケースは、PHP勉強会に出席されるような方はあまり出くわさないと思いますが、いざという時の豆知識として「ああ、そういえばこんな小手先技があったっけ。」と思い出して頂ければ幸いです。

結構企業の業務システムではIEオンリーなJavaScriptだらけで、showModalDialogもクラサバ時代のUIをWebで実現する為に使ってるんだろうなという現場もあります。そういった仕事に出くわした時は、ぜひ試してみて下さい。



プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2008-12-21 00:01:03
md5:add7127aad1e1c27acc166898cf9c21d
sha1:c7ed49ddd72fa6544e84f6aa59f5ef1f12eccd5b

PHP/セッションとクッキーの共存  

所有者: msakamoto-sf    作成日: 2005-05-26 08:13:47
カテゴリ: PHP 

「セッションとクッキーは共存できるのか?」に挑戦してみました。

今回のサンプル:添付ファイル/PHP/cookie-sessions.zip

RFC上、Multipleなset-cookieはオッケーっぽいので行けると思うのですが。

やってみました。つまるところsession_start() と setcookie()の両方を呼び出して、正常にクッキーがとれれば良いわけです。
→ できました。 サンプルのcookie-session2.phpを参照。

cookie-session2.php

<?php
session_set_cookie_params(60, "/", null, null);
session_start();
...
if(!isset($_SESSION["hoge"])) {
    ...
}
if(isset($_COOKIE["val1"])) {
	$_COOKIE["val1"] += 2;
	setcookie("val1", $_COOKIE["val1"]);
} else {
	setcookie("val1", 0);
}
...
?>


プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2008-12-16 08:16:21
md5:85cad2b6266cb52e86b7be822c03381b
sha1:d1f810818db1663ccd78dcbfb1bf1d07ce127d43

添付ファイル/PHP/cookie-sessions.zip  

所有者: msakamoto-sf    作成日: 2005-05-26 08:12:34
カテゴリ: PHP 添付ファイル 
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2008-12-16 08:13:27
md5:058e9939b72f0312e6cf2b32de06f2e4
sha1:fac4564b34a630f02d5551bab2fdc7d20158c312

PHP/ADODB/アンダースコア("_")を含むDB名で嵌った件  

所有者: msakamoto-sf    作成日: 2006-03-11 08:02:46
カテゴリ: PHP 

adodb.inc.phpの3670行付近、DSN形式をparse_url()で分解している箇所で、少なくともバージョン4.67と4.70の間で次のような違いがありました。

ADOdb 4.67:

if (strpos($db,'://')) {
    $origdsn = $db;
    $dsna = @parse_url($db); 

ADOdb 4.70:

if (strpos($db,'://')) 
    $origdsn = $db;
    $db = str_replace('_','%95',$db);
    $dsna = @parse_url($db);

・・・多分、parse_url()の仕様上そうなったのかもしれません。配列から値を取り出す場合は、rawurldecode()しています。

が。
http://phplens.com/lens/lensforum/msgs.php?id=14499&x=1
に有るように、"%95"はrawurldecode()しても戻らないんですよ。

→4.71では修正されたようです。というわけで、アンダースコアの問題で嵌っている方は最新版にしませう。


プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2008-12-16 08:04:31
md5:e4d6e0263b2c804f0818edda2f238bf0
sha1:f929ea13365857af8493ec67caa072989fffd02f