この度は拙作 PHP ライブラリ、Arcadian garden: PHP Unified Repository Engine (Ag:PURE) をお試し下さいましてありがとう御座います。
Ag:PURE は拙作ウェブページ Arcadian garden を構成するに当たって基盤として構築した、『ウェブサイト全体をバタバタと作る時に便利』であることを大命題に開発しているライブラリです。
近年、ウェブサイトの作り方は昔と違って様々な方法が登場しています。
企業システムでは CMS (Contents Management System) の導入も盛んでしょうか?
Wiki によってお手軽に作成している人もいるでしょうし、そもそもブログで済ませてしまっている人もいます。
オーサリングツールの類で作っている人もいるでしょうし、Powered by メモ帳の方もなにげに少なくないかもしれません。
ちなみに拙作ウェブページ Arcadian garden は PHP スクリプトをまるで HTML の様に多用してバタバタとテキストエディタで記述する手法で開発しています。
元々 WYSIWYG (What You See Is What You Get) 型のオーサリングツールが大嫌いな私ですので当然の帰結と言えますが、HTML の替わりに PHP を利用しているのには、テキストエディタで個々の文書をバタバタと作っていても処理の共通化とデザインの共通化を自動化したい、という要求があったからです。
(旧拙作ウェブページ Innocent Arcadia Millennium はこの辺りが共通化されていなくて、メンテナンスにとても苦労しました)
この要求を満たすには、各ドキュメントにシームレスに結合され、構築を阻害せず、かつ目立たず騒がない縁の下の力持ち的な隠れたフレームワークの存在が必要でした。
あたかも文章を書くかのように本題にのみ注力することができるライブラリです。
PHP でフレームワークやライブラリと言えば色々と有名ドコロがあったりもしますが、なかなかその様な用途のライブラリは存在しません。
と言うか、普通作っていても表に出てこないのでしょう。
それに色々と問題点もありました。
などなど、頑張れば回避可能な問題点から辛抱堪らん問題点まで多種多様で、結局自分で構築するに至りました。
ま~、
という最大の問題点に目をつぶることが出来なかった、とも言えます。
Ag:PURE は『ウェブサイト全体をバタバタと作る時に便利』を大命題としてしています。
従って Ag:PURE は以下のようなコンセプトの元に開発されています。
ON ERROR RESUME NEXT を書いて Err.Number を都度調べるか、ON ERROR GOTO *** で全部すっ飛ばすかの二者択一です。try ~ catch 構文が利用できるようになりましたが、PHP4 までのエラー処理フローは依然として残っており、両者は同居、と言うより混在しています。
Ag:PURE は大別すると以下のパッケージに分けられます。
Ag:PURE は非商用、商用問わず非常に緩い制限で利用することが出来る「修正済み BSD ライセンス」の Ag:Techsol 適用版によって提供されます。
ライセンス文書は以下を参照してください。
Ag:PURE はピュアに PHP だけで実装されているため、基本的に PHP が動作する環境であれば動作すると思われますが、全ての環境において正常動作を保証するものでありません。
Ag:PURE は以下の環境での実行を前提としています。
Ag:PURE は導入するだけならとても簡単です。
もちろん無理に全部の機能を使う必要はありません。
(というか完全に Arcadian garden の必要に応じて作ったライブラリなので、私以外の誰かが全部の機能を使うなんて、そうと意識しないかぎりは無理だと思います)
Ag:PURE のパッケージを PHP から読み込み可能な場所に、ディレクトリ構成を維持したまま展開してください。
PHP から読み込み可能な場所は、一般に HTTP サーバが実行されているユーザに対してアクセス権が設定されているディレクトリです。
HTTP サーバの実行ユーザとアクセス権の設定に関しては千差万別なので、ご利用のサーバの環境をご確認下さい。
Ag:PURE の初期化モジュール(ブートモジュールと呼びます)は pure.inc です。
pure.inc は Ag:PURE を展開したディレクトリの最も上位に用意されているはずです。
Ag:PURE を利用したい任意の PHP スクリプトから、以下のようにインポートします。
// Ag:PURE ライブラリのインポート require('pure.inc');
ブートモジュールは呼び出されるとコアライブラリのインポートと初期化を行います。
ウェブページ全体を Ag:PURE ライブラリの管理下で実行したい場合(Arcadian garden はこの形式です)、個々の PHP スクリプトの先頭でいちいち前述のインポート処理を行うのはナンセンスです。
その様な場合、PHP の環境設定ファイル php.ini の auto_prepend_file ディレクティブが有効です。
auto_prepend_file ディレクティブは PHP スクリプトが実行される前に最初にインポートされるモジュールを指定します。
例えば、pure.inc をインポートするモジュール prepend.php を /usr/local/apache2/htdocs 配下に作るとします。
<?php // Ag:PURE ライブラリのインポート require('/usr/local/apache2/htdocs/lib/pure/pure.inc');
次ぎに php.ini の auto_prepend_file ディレクティブを以下のように設定します。
auto_prepend_file = /usr/local/apache2/htdocs/prepend.php
この様にすることで、全ての PHP スクリプトから自動的に Ag:PURE の機能を利用できるようになります。
また auto_prepend_file ディレクティブはディレクトリ単位で変更可能なディレクティブですので、httpd.conf や .htaccess で特定のディレクトリにのみ定義するのも便利です。
Microsoft IIS の場合には Apache + PHP の場合のような柔軟なディレクティブ定義が出来なくなっている模様です。
一応 PHP の方に、レジストリを参照して php.ini の設定を上書きする機能が用意されている模様ですので、詳しくはPHP マニュアルの「インストールと設定 - 実行時設定 - 設定を変更するには」を参照してください。
作者と致しましては、基本的に IIS での利用は推奨していません。
コアライブラリの初期化後は以下の機能が提供されます。
コアライブラリ PURE クラスはエラー処理を標準化します。
PHP スクリプト実行中に発生した通知を含むトラップ可能な全てのエラーは defaultErrorHandler メソッドに捉えられ、対応する例外に発行され直されます。
さらにキャッチされなかった例外は defaultExceptionHandler メソッドに送られ、例外画面が生成されます。
コアライブラリの提供する機能で、縁の下の力持ちになりえるのがこのエラー処理の標準化機能です。
エラー処理の標準化機能は通知を含む全てのエラーをトラップして例外に置き換え、かつ標準の例外ハンドラを用意することでキャッチされなかった例外が発生した際にエラーの内容、発生した場所を明確にします。
特に通知を含む全てのエラーをトラップするところが重要で、これは初期化されていない変数から読み込んだり、初期化されていない変数が条件式に現れた際の通知エラーも例外としてスローされることを意味します。
つまり(初心者にありがちな)ケアレスミスやタイプミスを例外として示してくれるわけです。
トラップできないエラー(パースエラーなどの致命的なエラー)は従来の PHP 標準の処理で行われることに注意してください。
特に終了フィルタ内でトラップできないエラーが発生した際には非常に分かりづらい状況に陥ってしまいます。
php.ini の log_errors ディレクティブなどと併用することを推奨します。
コアライブラリは簡易的なリポジトリ管理の機能を持っています。
このリポジトリ管理の機能は JAVA ライクであり、パッケージの概念を元にモジュールを読み込むことが出来ます。
JAVA と異なり、PHP では名前空間のサポートが成されていません。
Ag:PURE がサポートするパッケージはモジュールの論理名とディスク上の物理的な場所を結びつける意味でのみ効果を持ちます。
パッケージが異なっていても同一のクラス名は定義できないことに変わりはないことに注意してください。
PHP も 6.0 から正式に名前空間のサポートがなされる模様ですが………
コアライブラリは初期化されると、エラー画面を正常に出力できるようにするために出力をバッファリングします。
バッファリングされた出力内容はスクリプトの終了時にコアライブラリの終了処理 finalization メソッドを通って出力されます。
現在のバージョンでは finalization メソッドは終了フィルタの機能を提供します。
終了フィルタが設定されていない場合には終了処理はバッファリングされている内容をそのまま出力します。
コアライブラリの終了処理が導入する終了フィルタは、PHP スクリプトの実行結果としてクライアント側に送信される出力内容に一定の整形処理を行いたい場合の、統一的な手段です。
終了フィルタを実装するには以下の手順を行います。
以下に終了フィルタの実装例を示します。
/** * 終了フィルタの実装クラスの例です。 */ class SampleFilter extends PURE_FinalFilter { /** * フィルタ処理の実装です。 * * @param string $source フィルタリングする文字列 * @return string フィルタリング後の文字列 */ public function execute($source) { // ... フィルタ処理 ... return $source; } } // コアライブラリへの登録 PURE::addFinalFilter(new SampleFilter());
なお、Brownie 形式テキストでは自動的に起動する終了フィルタが標準で定義されています。
詳しくは Brownie 形式テキストの章を参照してください。
Ag:PURE が提供するセッション管理では、グローバルセッションとサブセッションの2つが導入されます。
以下にグローバルセッションとサブセッションの違い、用途を説明します。
Ag:PURE 標準のセッション管理を利用したい場合、pure.session パッケージをインポートします。
pure.session パッケージをインポートすることで、自動的にセッションハンドラが置き換わり、可能であればサブセッションが復帰されます。
<?php PURE:import('pure.session.*');
グローバルセッションには SESSION クラスを通してアクセスします。
<?php SESSION::open(); // グローバルセッションを開きます $value = SESSION::get('key'); // グローバルセッションからパラメータを取得します SESSION::set('key', $value); // グローバルセッションにパラメータを格納します
サブセッションはそれよりも若干複雑です。
サブセッションを利用する場合、グローバルセッション中でサブセッションを維持するためのサブセッション ID を明示的にフォームから引き渡す必要があります。
フォームからリクエストを受け取ったスクリプトは、今度はサブセッションをリクエストから復帰する必要があります。
これは SESSION クラスの createSubSession メソッドと、getSubSession メソッドの組み合わせにより実現されます。
<?php $subSession = SESSION::createSubSession(); ?> <FORM action=procedure.php> <?php // サブセッションを維持するサブセッション ID フォームを出力します echo $subSession->getIdForm(); ?> 名前: <INPUT type=text name=name size=30 maxlength=30><BR> パスワード: <INPUT type=password name=password size=30 maxlength=30><BR> <INPUT type=submit value="ログイン!!"> </FORM>
<?php $subSession = SESSION::getSubSession(); // サブセッションの復帰 // ...フォームに関する処理 $subSession->close(); // サブセッションの解放
サブセッションにアクセスするためには、SESSION クラスの createSubSession メソッドないし、getSubSession メソッドから得られた SubSession クラスのインスタンスを利用します。
SESSION クラスは open メソッドによりセッションを開始する際に、サブセッションを確認します。
渡されたサブセッション ID が既に破棄されていたり、そもそも生成した物でなかった場合には ESessionSecurityException 例外を発生させます。
これは成り済ましによるリクエストや、多重投稿を防ぐ一助になります。
この処理を正常に動作させるためにも、使用済みのサブセッションは速やかに解放することをお勧めします。
簡易タグライブラリは HTML などのテキスト中に記述された XML ライクなエレメントを解析して再フォーマットする JSP ライクな仕組みです。
しかし、簡易タグライブラリはエレメントの動作を定義する基底クラスである Taglib_CustomElement クラスと、タグのパース能力を持った Taglib_Parser クラスから構成されますが、これらは特定の用途に特化した能力は持っていません。
簡易タグライブラリ自体はテキストからエレメントによって定義づけられた文書構造を解析する仕組み自体を提供するに留まります。
特定の用途に関しては簡易タグライブラリを用いた個々の実装に依存します。
Ag:PURE では簡易タグライブラリの機能を用いた終了フィルタを用意しています。
簡易タグライブラリの機能を用いた終了フィルタは JSP とは異なり、以下のような特徴を持っています。
簡易タグライブラリの機能を用いた終了フィルタは Taglib_Parser を内部で隠蔽した Taglib_Filter クラスにより実装されます。
簡易タグライブラリを利用する場合、エレメントを Taglib_CustomElement クラスを継承して定義し、Ag:PURE の終了フィルタに簡易タグライブラリの終了フィルタ Taglib_Filter クラスのインスタンスを登録します。
以下に例を示します。
<?php require('pure.inc'); // 簡易タグライブラリを用いた終了フィルタのクラスをインポートします // 簡易タグライブラリを実装した pure.fw.taglib.* パッケージは暗黙にインポートされます PURE::import('pure.fw.filter.final.TaglibFilter'); /** * TEST:DOCUMENTエレメントの実装クラスです。 */ class CustomElement_TEST_DOCUMENT extends Taglib_CustomElement { /** * 開始タグが置き換わるHTMLを生成します。 * * @return string 開始タグが置き換わるHTML */ public function doStartTag() { $html = ""; $html .= "<!DOCTYPE html public \"-//W3C//DTD HTML 4.01//EN\">\n"; $html .= "<HTML>\n"; $html .= "<HEAD>\n"; $html .= "<TITLE>".htmlspecialchars($this->getAttr('title'))."</TITLE>\n"; $html .= "</HEAD>\n"; $html .= "<BODY>\n"; return $html; } /** * 終了タグが置き換わるHTMLを生成します。 * * @return string 終了タグが置き換わるHTML */ public function doEndTag() { $html = ""; $html .= "</BODY>\n"; $html .= "</HTML>\n"; return $html; } } // 終了フィルタにタグライブラリのパーサ/フォーマッタを登録 $filter = new Taglib_Filter(); $filter->registerElementClass('TEST', 'DOCUMENT', 'CustomElement_TEST_DOCUMENT'); PURE::addFinalFilter($filter); ?><TEST:DOCUMENT title="文書タイトル"> <P> 本文です。 </P> </TEST:DOCUMENT>
出力結果は以下のようになります。
<!DOCTYPE html public "-//W3C//DTD HTML 4.01//EN"> <HTML> <HEAD> <TITLE>文書タイトル</TITLE> </HEAD> <BODY> <P> 本文です。 </P> </BODY> </HTML>
Brownie 形式テキストは HTML へ整形されることを目的に記述される、構造化されたテキストファイルです。
PukiWiki などを利用したことがある方は、その文法の簡易版だと思っていただいて間違いありません。
(事実、PukiWiki の文法を多分に意識しています)
しかし Brownie 形式テキスト整形ライブラリのそれらと違うところは「組み込み用途である」という部分です。
Brownie 形式テキスト整形ライブラリだけでは当然ウェブサイトは作れません。
そもそも PukiWiki の様なオンラインの編集インターフェイス自体が存在しません。
Brownie 形式テキスト整形ライブラリはあくまでも上位のプログラムから呼ばれるためのライブラリとして存在し、掲示板の投稿文や、はめ込みで作成されるページの本文などの特定範囲の処理に利用します。
Brownie 形式テキスト整形ライブラリは組み込み用途であるが故に Brownie 形式テキストだけでウェブサイトを構築する能力は持ちませんが、Brownie 形式テキストを整形して HTML 化する終了フィルタを定義しています。
Brownie 終了フィルタは Ag:PURE コアライブラリの終了処理で、以下の条件の場合に自動的に起動します。
この条件を満たすためには、拡張子 ".brn" のリソースに対するリクエストが PHP スクリプトとして処理されなければなりません。
通常、PHP が起動するように設定されている Apache の httpd.conf には以下のような設定がなされている筈です。
AddType application/x-httpd-php .php LoadModule php5_module modules/libphp5.so
ここに更に以下の設定を追加します。
AddType application/x-httpd-php .brn
これで拡張子 ".brn" も PHP スクリプトとして解釈されるようになり、結果として終了処理で Brownie 形式テキストとしてフォーマットされます。
auto_prepend_file ディレクティブを利用して Ag:PURE を積極的に初期化していない場合、Brownie 形式テキストの先頭で明示的に Ag:PURE を初期化する必要があることに注意してください。
なお、Brownie 形式テキスト整形ライブラリは BODY 内部の本文のみを生成するテキストフォーマッタです。
従って Brownie 形式テキストをフォーマットしただけでは HTML 文書として必要なヘッダ情報などの情報は自動的には付加されません。
Brownie 終了フィルタはこの問題を簡易テンプレート機能を実装することで解決します。
Brownie 終了フィルタは Brownie 形式テキストをフォーマットした後、整形後のテキストを適用するためのテンプレートを検索します。
テンプレートはカレントディレクトリ (通常はリクエストされた文書が存在するディレクトリ) から順に上層のディレクトリに遡りつつ、"template.brownie" という名前のテンプレートファイルを探します。
テンプレートファイルが見付かった場合、Brownie 終了フィルタはテンプレートファイルに整形後の HTML をはめ込みます。
テンプレートファイルは通常、HTML ファイルです。
HTML ファイル中に以下のキーワードを挿入することで、整形後のテキストをはめ込むことが出来ます。
テンプレートファイルが見付からない場合には、Brownie_Filterクラスの標準テンプレートが利用されます。
単純で強力なメール送信処理を提供します。
このメール送信処理は PHP の mail 関数には全く依存しません。
添付ファイルの処理や、HTML メールなどで利用されるマルチパートメッセージの管理、そして SMTP サーバへ直接接続しての送信処理を一貫して行います。
Ag:PURE 標準のメール送信機能は PHP の mail 関数には全く依存しないで SMTP を直接操作するかわりに、SMTP-AUTH などの認証機構に対応していないことに注意してください。
単純な SMTP にのみ対応します。
PHP 標準の PDO に関してデータソースを管理する統一的な手段を提供します。
OCI8 関数群を隠蔽した PDO ライクなクラスライブラリと、データソースを管理する統一的な手段を提供します。
PHP 5.2.4 現在、PDO の OCI ドライバは実験段階であり、いくつかの致命的な不具合が確認されています。
Oracle データベースを利用する開発では、OCI8 関数群を直接利用するか、Ag:PURE が提供する Oracle OCI ライブラリを利用することをお勧めします。
pure.util パッケージ内にその他の様々な関数が定義されています。
これら関数は度々使うことがありながらも PHP 本体に実装されておらず (もしくは機能が中途半端で)、プロジェクト毎に再開発を強いられる物をざっくばらんに詰め込んだ物です。
詳細は API リファレンスを参照してください。
Arcadian garden: Server Side eXtension (Ag:SSX) は、Ag;PURE と同様に拙作ウェブページ Arcadian garden を構築するに当たって構築した、サーバ側処理を簡素化するためのライブラリです。
無論、Arcadian garden を構築する過程で必要とした物ですので Arcadian garden のシステムデザインに大きく影響されているのは如何ともし難い事実ですが、どうしても Arcadian garden 固有にならざるを得ない部分以外を共通化しておけば後々使うこともあるのではないかと、Ag:SSX として分離、Ag:PURE に標準添付しました。
なお、Ag:SSX に収録されているパッケージのうち、ある程度の動作試験を経て標準ライブラリに昇格するに相応しいと判断した物は随時標準パッケージへ昇格します。
論理的な構造でウェブページを構成しているとき、ナビゲーションメニューの構築の面倒くささに辟易したことはないでしょうか?
一連の続き文書の先頭、直前、直後、最後、更に直上へジャンプするリンクを作成するのは一般的ですが、これを作成するのはなかなかに骨が折れる作業です。
例えば文書A、B、CのBとCの間に新しい文書Dを挿入してA、B、D、Cという並びにしたいとき、文書Bと文書Cのナビゲーションメニューを共に修正する必要が発生します。
また、文書A、B、Cの直上の文書Eが文書Fに替わってしまった場合、結局のところ文書A、B、Cの全てのリンクを修正する必要が発生します。
Ag:SSX が提供するサイト構造ライブラリは、ディレクトリに構造定義ファイルを置いておくことで、文書の上下左右の論理構造を記述、その情報からナビゲーションメニューの情報を自動取得するライブラリです。
例えば、前述の例を用いて、あるディレクトリに文書Fを先頭にして文書A、B、D、Cが論理構造を持っているとき、以下のような構造定義ファイルを用意します。
<directory> <parent name="G.php" /> <documents> <document caption="F" name="F.php"> <documents> <document caption="A" name="A.php" /> <document caption="B" name="B.php" /> <document caption="D" name="D.php" /> <document caption="C" name="C.php" /> </documents> </document> </documents> </directory>
この構造ファイルは文書A、B、D、Cの順序と、それぞれの親文書が文書Fであることを表します。
さらに文書Fは親ディレクトリの文書Gが親文書であることも表しています。
この情報を簡単に取得してリンク情報を作成することが出来るのが Ag:SSX のサイト構造ライブラリです。
例えば前述の例で文書DのスクリプトであるD.phpに以下のように記述すると論理構造が取得されます。
<?php require('pure.inc'); PURE::import('com.arcadiangarden.ssx.struct.*'); $navigator = Struct_Navigator::getCurrentStructNavigator(); ?>
Struct_Navigator クラスの getCurrentStructNavigator スタティックメソッドは、カレントディレクトリの directory.xml を読み込んで Struct_Navigator クラスの実装を返します。
Struct_Navigator クラスには、ナビゲーションメニューの各情報を取得する up、first、prev、next、last 各メソッドと共に、HTML のヘッダに出力する LINK エレメントを一括して生成する links メソッド、ヒエラルキーメニューを作成する hierarchyHtml メソッドなどの便利なメソッドを用意しています。
ヒエラルキーメニューを作成する場合、現在のディレクトリから遡ってドキュメントルートまで構造定義ファイルが準備されている必要があります。
hierarchyHtml メソッドは構造定義ファイルが取得できなかったディレクトリをルートディレクトリであると認識します。
Ag:PURE が提供するコアライブラリ、標準ライブラリ、Ag:SSX の API リファレンスを用意していますので、ご利用下さい。
Ag:PURE API リファレンスは、phpDocumentor により作成されています。
なお phpDocumentor は PECL のコーディング規約を前提としており、パッケージ区切に "." を利用すると "-" に置き換えられてしまうなど Ag:PURE と微妙に相容れない部分があります。
このため Ag:PURE API リファレンスの出力に際しては phpDocumentor に若干の修正を加えて利用しています。