目次

4. 拡張機能

拡張機能のセクションではユーザーインターフェースと関係のない しばしば必要とされるアプリケーション機能を提供する非GUIクラスを カバーしています。いくつかの拡張クラスはコア機能に依存していますが、 その他は独立したクラスとなっています。

拡張クラスは prepend.php3 によって自動的にインクルー ドされない点でコアクラスとは区別されます。必要に応じて明示的に クラス定義をインクルードするか prepend.php3 を改変する必要があります。

4.1 Cart

Cartクラスはプログラム上は独立クラスですが、 インスタンスが何らかの持続性を有している場合にのみ意味があります。 Cartクラスは、その start() 関数でセッション変数として 自身を自動的に登録します。

Cartクラスは買い物かご(Shopping Cart)を実装しています。 現時点では、買い物かごの中の品物はそれぞれ独立しています。 かごは単純な品物だけを持つことができます。それが機能するために他の品物を 必要としたり、それに依存する品物への基礎を提供するといった複合品目の サポートは将来追加されます。

単純品目の例としては、他のオプションを持たない品物すべて、 例えばリンゴや本などがあげられます。複合品目の一般的な例としては、 ピザ(アメリカ、イタリアいずれのスタイルにおいても、正しく機能する ためにはトッピングとチーズが必要です)およびコンピュータシステム (正しく機能するためには、ケース、マザーボード、RAM、ビデオカード等が 必要です)があります。

注意: Cartリリース5まではコアクラスで した。もしあなたのアプリケーションが Cart クラスを使って いるなら、あなたは明示的にあなたのファイルで指示されている prepend.php3ファイル内に include("cart.inc") 文を 加えなければなりません

注意:ページ管理関数はcart機能について Cart クラスを準備し開始する機能をもはやサポートしません。 cartを自動的に開始する代わりにSessionauto_init 機能を用いるか、cartを手動で設定することが推奨されます。

インスタンス変数

classnameシリアル化ヘルパー:このクラスの名前です。
persistent_slotsシリアル化ヘルパー:全ての持続的スロットの名称。
itemカゴの中の品物を示す多次元配列
currentItem品物の位置を示すカウンター
アクセス可能なインスタンス変数

インスタンスメソッド

アクセス可能なインスタンスメソッド

check($art)

指定した品目番号$artを持つ品物がカゴの中にあるかどうかを チェックします。ブール値と整数値の配列を返します。もしブール値がtrue なら カゴ中の品目番号に対応する品種の個数が戻ります。

reset()

現在のカゴの中のすべての品物を削除し、$this->currentItem を1に リセットします。常にtrueを返します。

num_items()

現在の買い物カゴの中の品目数を返します。もしカゴが空ならfalseを返します。 互換性上の理由から、この機能は tot_arts としても存在します (が、もしこの名前を使用した場合には警告が出力されます)。

add_item($art, $num)

品目番号$artを持つ品目を$num個現在の買い物 カゴに追加します。買い物カゴ内の $art の位置を示す数字 (位置番号)を返します。

remove_item

もし十分な個数が 買い物カゴから品目番号 $art を持つ品目を $num 個削除します。 ただし、削除する個数以上の物が買い物カゴにある場合に限ります。 もし成功すれば $artの位置番号を返し、もしカゴから取り除くのに$artが 十分な個数を持っていなければ false を返します。もしこの関数が false を返したら カゴはいかなる変更も受けません。

set_item

買い物カゴの中の品種番号 $art の個数を正確に $num 個に セットします。もし $num がゼロならば、品目はカゴから取り除かれます。 買い物カゴ中の $art の位置番号を返します。

show_all()

もし買い物カゴが空ならば、show_empty_cart() を一度コールし 復帰します。

show_item_open()を買い物カゴの一覧表示を開始する時に一度コールし、 次に買い物カゴの各品物ごとに show_item() をコールします。買い物カゴ 一覧表示の終了時に show_item_close() を一度コールします。

show_item($art, $num)

この関数はユーザーが提供するべきです。カートからある一つの品物を 表示するための HTML 文を生成します。$art はその品物の品目番号で あり、カゴにはそれが $num 個あります。

show_cart_open()

この関数はユーザーが提供するべきです。買い物カゴ一覧を表示するときに 先立って表示される HTML を生成します。

show_cart_close()

この関数はユーザーが提供するべきです。買い物カゴ一覧を表示するときに 最後に表示される HTML を生成します。

show_empty_cart

この関数はユーザーが提供するべきです。空のカゴを象徴する適切な メッセージを出力します。

show_item() の実装を提供するために Cart の サブクラスを用います。


class My_Cart extends Cart {
  var $classname = "My_Cart";

  // 品目の個数を求める
  var $database_class = "DB_Article";
  var $database_table = "articles";
  var $db;
  
  var $sum = 0;

  function show_cart_open() {
    printf("<table class=cart_table>\n");
    $this->sum = 0;
  }
  
  function show_cart_close() {
    printf("</table>\n");
    printf("全部で %s 個あります\n", $this->sum);
  }

  function show_item($art, $num) {
    if (!is_object($this->db)) {
      $class    = $this->database_class;
      $this->db = new $class;
    }
    
    $query = sprintf("select * from %s where artid = '%s'",
      $this->database_table,
      $art);
    $this->db->query($query);

    while($this->db->next_record()) {
      printf(" <tr class=cart_row>\n  <td class=cart_cell>%s</td>\n",
        $this->db->Record["name"]);
      printf("  <td class=cart_cell>%s</td>\n", 
        $this->db->Record["price"]);
      printf("  <td class=cart_cell>%s</td>\n",
        $num);
      $rowsum = $num * $this->db->Record["price"];
      $this->sum += $rowsum;
      printf("  <td class=cart_cell>%s</td>\n",
        $rowsum);
      printf(" </tr>\n");
    }
  }
}

カゴを使用する際には、Cart サブクラスのインスタンスを作成し、 start()をコールしてください。これにより、自動的にcartが 登録されます。

local.inc 中のSession サブクラス中の スロット$auto_initを値setup.incに設定し、 以下のコードを含む同名のファイルを作ることが推奨されます。


  global $cart;               // $cart はグローバル変数
  $cart = new My_Cart; // My_Cart インスタンス名を $cart にする
  $cart->start();          // そしてそれにそれ自身を登録させる

作成したCartを動作させる際には、add_item()remove_item() を使用して下さい。


  $cart->add_item("101", 2);    // "101" 番を2個追加
  $cart->remove_item("101", 1); // "101" 番を1個削除

カゴの中身を表示するためには、show_all()を使用して下さい。


  $cart->show_all();    // とにかくカゴの中身はなんだい?

Cartを用いるにあたって(On using Cart)

Cart クラスを用いる際には、データベース中に自分の店が 販売する全ての品目をリストする新しいテーブルを定義する必要があります。。 PHPLIBとMySQLの組み合わせでは、それぞれの仮想Webサーバー毎に PHPLIB のインスタンスを生成し、それぞれの顧客ごとに新しいデータベースを 生成することが推奨されます。 このデータベースは、物品リストのようなアプリケーション固有の テーブルと同時にactive_sessionsやauth_userテーブルを保持する必要があります。 言い換えると、MySQLと組み合わせる場合には、PHPLIBとMySQLディレクティブとで database_nameを共有することは絶対にやめるべきです。 もしそうしたとしても何のサポートもありません。 (もっとも、PHPLIB はオープンソースであり、あなたは あなた自身のリスクにおいて使っているので、私たちの言うとおりやったと しても何の保証もありませんが・・)

ここで、大変簡単な新規テーブル articlesを 以下のような構造で定義したと仮定しましょう。


# テーブル 'articles' の構造
#
CREATE TABLE articles (
  name text,
  price float(8,2),
  artid int(11) DEFAULT '0' NOT NULL auto_increment,
  PRIMARY KEY (artid)
);

このテーブルは artidと呼ばれる品目番号を持ち、それぞれの artidごとに品目の説明 name と価格 price があります。この最小限の定義に品種グループを追加するとか、 品種の画像などを格納するための BLOB を追加するなど目的に応じて拡張すること が可能ですが、例を示すという意味ではこれで充分です。

このテーブルに目的に応じていくつかの製品を登録して下さい。

次なるステップは、cart クラスをPHPLIBに教えることです。 そうするためには以下の3つのステップが必要です。

ここまでの作業によりPHPLIBを用いる全てのページでデフォルトで利用可能な $cartオブジェクトが作成されました。このオブジェクトは セッション開始時に自動的に生成され、PHPLIB のセッション管理によって ページからページへと伝達され、セッション記録を刈り取るガーベージコレクションで 削除されます。cartクラスについてこれ以上心配する必要はなく、単純に page_open()page_close() の間で常に使用する ことができます。PHPLIBが残りの作業を行います。

実際Cartクラスはほとんど何もしません。 このクラスは、ユーザーが購入した商品の記録を保持する配列 $cart->item[] を維持します。 各要素$cart->item[$x]は、$cart->item[$x]["art"] (ユーザーの購入希望商品の品目番号)と$cart->item[$x]["num"] (購入希望のその品目番号の商品の個数)からなっています。 $cart->currentItemは、$cart->item[]に商品を 追加する際に用いられる$xの次の値です。

買い物カゴに品目を追加するには以下のようにして下さい。
You add articles to the shopping cart with


$x = $cart->add_item($art, $num)

これにより品目番号$art$num 個の品物がカゴに 追加されます。既に同じ品目番号の品物を持っていた場合には、この品目の個数が $numだけ加算されます。 そうでなければ新しい品目エントリが作成され、$num にセットされます。 この関数は、インデックス番号$xをその品目の$cart->item[] 配列に返します。

買い物カゴから品物を削除するには、以下のようなコードを使用します。


$x = $cart->remove_item($art, $num)

これにより、カゴに十分な個数の商品が入っていたら、カゴから当該品目番号 $art を持つ商品を$numだけ削除します。 カゴに$art がないか、カゴに$art$num 個 ない場合には、この関数はfalseを返し、カゴからは何も削除しません。 それ以外の場合、品目番号$artを持つ商品が$num個だけ カゴから取り除かれ、その結果当該品目の個数がゼロになったら配列からその要素は 削除されます。

ある品種についてカゴの中にいくつあるかチェックすることができます。


list($have, $num) = $cart->check($art)

このチェック関数は二つの要素をもつ配列を返します。対象の品目がカゴの中に あったら最初の要素 $have は true です。$have が true であれば、$num はカゴの中のその品目ごとの個数を保持し、 そうでなければ $num は未定義です(実際には 0 ですが、それを あてにしてはいけません)。

ついに私たちは以下の関数を使用します。


$cart->show_all()

このコードは、買い物カゴを走査し、Example_Cartに対して商品のリストを 生成する際にコールすることが可能です。 この関数は、最初に$cart->show_cart_open() をコールします。 作成したサブクラスでこの関数のコード実装を提供することが可能です。 次にカゴの中の各商品について$cart->show_item($art, $num)を コールします。 デフォルトのCartの実装では意味のあることはしないようになっていますが、 Example_Cartにおいてより洗練されたコードを提供することも可能です。 カゴの一覧表示の終わりに$cart->show_cart_close()がコールされます。 ここでも独自のコードを実行させることができます。

前のセクションの例では、Cart サブクラスのより洗練された実装を 示しています。その実装においてshow_cart_open()は、 (CSSクラスでフォーマットされた)表の開始タグを生成し、 カウンター $cart->sumをゼロにセットしています。

show_cart_close()では表が閉じられ、$cart->sum の カウンターが表示されます。

容易に想像できるかと思いますが、show_item($art, $num) はそれぞれの 品目番号についてデータベースに問い合わせを行い、記述と価格を取り出し、最終的に 各商品の個数を考慮しながら全ての値段を合計しています。 更にこの関数は、表の行を作成し、顧客に見易い伝票を出力します。

4.2 Template

注意: もしこれが FastTemplates のようなものだと思っているならば、 注意して読んでください。そうではありません。

Template クラスにより、PHP のコードを全く含まない、しかし置換可能な 複数のフィールドを有するHTMLコードを保持することを可能にします。 このクラスは、置換用フィールドに任意の文字列を代入することが可能な 関数を提供します。代入する文字列は、表全体といったように非常に 大きなものとすることができます。

インスタンス変数

classname文字列。シリアル化ヘルパ。このクラスの名前です。
debug論理値。trueに設定された場合、このクラスはデバッグ用出力を行います。
unknowns"keep", "comment", "remove" (デフォルト)のどれかです。 Templateの出力時に未解決の変数名をどのように扱うかを定義します。 "keep"が設定された場合、それらの変数名はそのままにされます。 "comment"が設定された場合、未解決の変数名はエラーを報告するHTMLコメントに変形されます。 "remove"設定された場合、未解決の変数名は暗黙の内に削除されます(デフォルト)。
halt_on_error = "yes""yes" (デフォルト), "report", "no" のどれか一つ。 Temlateのエラー処理条件を定義します。"yes"に設定された場合(デフォルト)、 エラーが報告され、実行が中断されます。 "report"が設定された場合にはエラーが報告され"false" を返しますが、実行は継続されます。 "no"が設定された場合、エラーは暗黙の内に無視され、"false"を返しますが、実行は継続されます。
last_error = ""この変数に直近のエラーメッセージを保持します。
アクセス可能なインスタンス変数

file文字列のハッシュ。変数名をファイル名に変換する変換テーブル。
root文字列(パス名)。templateのファイルがロードされる際のベースになるディレクトリ。
varkeys文字列のハッシュ。変数名をその変数名に関する正規表現へと変換する変換テーブル。
varvals文字列のハッシュ。各varkeysについて変数名を置換する値に 変換する変換テーブル。
内部的なインスタンス変数

インスタンス・メソッド

アクセス可能なインスタンス・メソッド

Template($root = ".", $unknowns = "remove")

コンストラクタ。2つの省略可能なパラメータを付けてコールされます。 最初のパラメータはtemplateのディレクトリ(set_root() を 参照)を設定し、2番目のパラメータは未定義の変数の処理に関する ポリシーを設定します。

set_root($root)

この関数は、$root が適正なディレクトリかどうかチェックし、 templateを格納するベースディレクトリとしてこのディレクトリを設定します。

set_unknowns($unknowns = "keep")

この関数は未解決の変数名の処理に関する指針を設定します。設定される値は、 "remove", "comment", "keep" のどれかになります。 "keep"が設定された場合、それらはそのままにされます。 "comment"が設定された場合、未解決の変数名はエラーを報告する HTML コメントに変形されます。"remove" に設定された場合、 未解決の変数は黙って削除されます(デフォルト)。

set_file($handle, $filename = "")

この関数は、変数の初期値を定義するファイルの名前を定義します。 これは、$handle/$filenameの組もしくは$handle/$filenameの組の ハッシュでコールすることが可能です。 ファイルはこの時点ではまだ参照されず、必要な時に初めて参照されます。

set_block($parent, $handle, $name = "")

変数$parentは$handleで名前が指定された変数ブロックを保持することが できます。この関数は$parentからその変数ブロックを取り除き、 $nameという名前の変数リファレンスに置換します。 $nameを省略した場合、この名前は$handleと同じとみなされます。

set_var($varname, $value = "")

この関数は、変数の初期値を設定します。 初期値は、$varname/$value の組または$varname/$valiue の組のハッシュ でコールすることが可能です。

subst($handle)

この関数は、$handle で名前が指定された変数のうち、定義済みの 値を持つものを全て返します。結果文字列は "最終的なもの" ではありません。 すなわち、未定義の変数名に関する指針はまだ適用されていません。

psubst($handle)

この関数は、print $this->subst($handle) の短縮形です。

parse($target, $handle, $append = false)

この関数は、$handleという名前の全ての定義済み変数の値を置換し、 $targetという名前の変数に結果を格納するか付加します。

$handleが変数名の配列の場合、$appendは無視されます。 $handleという名前の変数は順番に置換され、それぞれの 置換処理の結果は$targetに格納されます。置換結果は、 $targetという名前の変数において順番に$handleに関する処理結果を たどることにより参照可能です。

pparse($target, $handle, $append = false)

print $this->parse(...) の短縮形です。

get_vars()

全ての定義ずみの変数の値のハッシュをその変数名がキーとして定義された 状態で返します。

get_var($varname)

$varname で名前が指定されている変数の値を返します。$varname が あるファイルを参照し、そのファイルがまだロードされていない場合には、 その変数はemptyとして報告されます。

変数名の配列が指定してコールした場合には、 それらの名前をキーとして定義したハッシュが返されます。

get_undefined($handle)

この関数は、$handle 中の未解決の変数名を変数名をキーとしたハッシュ (つまり、$a[$name] = $name の形式のハッシュ)として返します。

finish($str)

この関数は、$str の最終バージョンを返します。すなわち、 未解決の変数名に関する指針は、$str にも適用されます。

p($varname)

この関数は $varname で名前が指定された変数の値の最終バージョンを出力します。

get($varname)

この関数は $varname で名前が指定された変数の値の最終バージョンを返します。

haltmsg($msg)

この関数は、 作成するTemplateサブクラスにより上書きすることが可能です。 表示するエラーメッセージを引数としてコールされます。

内部インスタンスメソッド

filename($filename)

相対パス名でコールされた際に、この関数は $this->root が先頭に 付加されたパス名を返します。絶対パス名は変更されません。

filenameで指定されるファイルは存在している必要があり、 さもなくばエラーが発生します。

varname($varname)

この関数は指定した変数名に関する変数名の正規表現を作成します。

loadfile($handle)

ある変数が未定義(unknown)か空(empty) であり、ファイル名が後ろに付いている場合、後続のファイルが ロードされ、そのファイルの内容はその変数の値として代入されます。

halt($msg)

この関数はエラーが起きたときにコールされ、 $this->halt_on_error で定義されたポリシーに従ってエラーが処理されます。

このクラスは、文字列で一連の変数を管理します。これらの文字列は "{変数}" の形式で他の変数へのリファレンスを含んでいます。パースされるか 置換された際にこの変数へのリファレンスはその変数の値で置換されます。

変数の値は、set_var("name","value") をコールすることにより 手動で定義することが可能で、また、set_file("name","filename.ihtml") をコールすることによりファイルで定義することも可能です。 後者では、ファイルの内容は(可能な限り遅くまで)必要に応じてロードされ、 その変数の値として設定されます。

変数の値を定義する3番目の方法は、set_block("parent", "block", "name"); をコールすることです。この場合、 parent で名前が指定された変数の中の <!-- BEGIN block -->で始まり < !-- END block -->で終わる文字列ブロックが検索されます。 この文字列は変数 parent から取り除かれ、 block で名前が指定された変数に代入されます。 代わりにparent においてname への変数リファレンスが 置換されます。 オプションのパラメータ "name"が省略された場合、 "block" が代わりに使用されます。

Templateを直接使うか、または必要に応じて Templateのサブクラスを定義して下さい。

page.ihtml という名前のtemplateファイルを以下のように定義します。


<html>
 <head><title>{PAGETITLE}</title></head>
 <body bgcolor="#ffffff">
 <table border=1 cellpadding=4 cellspacing=0 bgcolor="#eeeeee">
  <tr>
   <td colspan=2><h1>{PAGETITLE}</h1></td>
  </tr>
  <tr>
   <td>{OUT}</td>
   <td>Content</td>
  </tr>
 </table>
 </body>
</html>

このファイルは、変数pagetitleおよびout という 名前の変数へのリファレンスを有しています。 これとは別の box.ihtml という名前のtemplateファイルは、 3つの変数リファレンス {TITLE}, {NUM}, {BIGNUM} を有するrowという 名前のブロックを有しています。


<!-- start box.ihtml -->
<table border=1 bgcolor="#cccccc" cellpadding=4 cellspacing=0>
 <tr>
  <td colspan=2><b>{TITLE}</b></td>
 </tr>
  <!-- BEGIN row -->
  <tr>
   <td>{NUM}</td>
   <td>{BIGNUM}
  </tr>
  <!-- END row -->
</table>
<!-- end box.ihtml -->

以下の php3 ファイルはこれらのtemplateの使い方を示しています。


<?php
  include("./template.inc");

  # $t という名前のTamplateのインスタンスを作成
  $t = new Template("/page/to/webserver/template", "keep");

  # page と box という名前の、ファイルを参照する変数を定義
  $t->set_file(array(
     "page" => "page.ihtml",
     "box"  => "box.ihtml"));

  # "box" から "row" という名前のブロックを抽出し、
  # "box" の {rows} へのリファレンスを作成
  $t->set_block("box", "row", "rows");

  # 変数 TITLE と PAGETITLE を定義
  $t->set_var(array("TITLE"     => "Testpage",
                    "PAGETITLE" => "hugo"));

  # NUM と BIGNUM を定義し、"row" を "rows" に追加...
  for ($i=1; $i<=3; $i++) {
    $n  = $i;
    $nn = $i*10;
    $t->set_var(array("NUM" => $n, "BIGNUM" => $nn));
    $t->parse("rows", "row", true);
  }

  # box から out を作成し、次に page から out を作成...
  $t->parse("out", array("box", "page"));

  # 完了したら出力
  $t->p("out");
?>
<hr>
<?php
  # もしあれば、未定義の変数をレポートします
  print implode(", ", $t->get_undefined("rows"));
 ?>


次へ 前へ 目次