タイトル/名前 | 更新者 | 更新日 |
---|---|---|
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 |
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とRegex.phpで$optionが、ひいては$format引数が使用されています。たとえばCallback.phpでしたら、コールバック関数(call_user_func)に唯一PHPスクリプトからプログラマーが渡せる引数として利用されていますし、Regex.phpでは同様で、内部で分岐こそしていますが、基本的にはpreg_matchに渡す正規表現として使用されています。
$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要素に + _(キー名)みたいな形で生成される裏技。
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という選択肢も出来たわけだし色々かも。)
最後のアップデートが2005年6月前後のxdebugのメモ。PHP4がまだ現役だった頃ですが、既にxdebugは有名だった気がします。
PHP-4.3.11 | c:\php\ |
php.ini | c:\windows\php.ini |
extension_dir | c:\php\extensions\ |
Apache2 | c:\program files\apache group\apache2 |
ダウンロードできます。ただ、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 の項目が表示されれば動作完了です。
詳細は下記公式ドキュメント参照。
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にプロファイルログを読み込ませると、関数の呼び出し順序や回数、時間などが分かりやすく確認できるのでお奨めです。
高機能な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/
とでも実行しておいてください。
Smartyのコマンドタグは、"{"で始まり"}"で終わるのがデフォルトです。しかし、これだとJavaScriptの関数と同じなので、不便です。
そこで、XOOPSやYakiBikiでは次のようにして、"<{"と"}>"に変更しています。
$smarty = new Smarty; $smarty->left_delimiter = "<{"; $smarty->right_delimiter = "}>";
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が発生します。)
register_object()に関しては、この"_"で始まる要素へのアクセス制限機能は適用されないことに注意してください。
このオブジェクト割り当てを調べたときの過程をメモっておきます。
まず、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);?>
になってました。
先の調査結果をふまえて、_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__);
みたくなってました。
とあるライブラリを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を若干修正しておく。
@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%;...
ここら辺は大体こんな感じで、細かくはお好みでいつも手を抜いたり凝ったりしている箇所。
次が本題。
最初、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
に設定が書き込まれちゃうんですよ!!!!
違うの違うの違うの~~~~~!!!そっちじゃねぇ~~~~!!!
なんでかは置いておきまして、答えを先に。
> 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の設定値の秘密は、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'); } ...
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環境変数を設定することで、好みの場所のPEAR設定ファイルを参照することができる、と分かりました。
ちなみに、Windows版のPHP5では残り二つがどうなるかというと・・・
> php -r "echo getenv('SystemRoot');" C:\WINDOWS > php -r "echo PHP_SYSCONFDIR;" C:\php5
と言う形になり、デフォルトで
C:\WINDOWS\pear.ini
になるのも納得できました。
第38回PHP勉強会で、殆どPHPが出てこない発表をして参りました。その時の資料です。
下記は発表の時に動かして見せたコードです。何の説明も無しに話を進めてしまったのは不味かったかなと反省してます。
多分IEの裏側を覗いてAPIレベルの挙動を確認したり、showModalDialog()というIEオンリーなJavaScriptを使用するケースは、PHP勉強会に出席されるような方はあまり出くわさないと思いますが、いざという時の豆知識として「ああ、そういえばこんな小手先技があったっけ。」と思い出して頂ければ幸いです。
結構企業の業務システムではIEオンリーなJavaScriptだらけで、showModalDialogもクラサバ時代のUIをWebで実現する為に使ってるんだろうなという現場もあります。そういった仕事に出くわした時は、ぜひ試してみて下さい。
「セッションとクッキーは共存できるのか?」に挑戦してみました。
今回のサンプル:添付ファイル/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); } ... ?>
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では修正されたようです。というわけで、アンダースコアの問題で嵌っている方は最新版にしませう。