(注:記事は執筆時の情報に基づいており,現在では異なる場合があります)

 ステップ6からはいよいよ中級編です。まずは,コードの再利用性,安全性,メンテナンス性の向上を目標に,今後登場するPHPの新版で重要になってくる,オブジェクト指向プログラミングについて解説しましょう。

図1●コースと時間を入力すると請求金額を計算するアプリケーション
リスト1
リスト2
リスト3
リスト4
 図1[拡大表示]を見てください。携帯電話の月別請求金額を計算するWebアプリケーションの画面です。HTMLフォーム上で,料金コースを選択し時間(単位は分)を入力して計算ボタンをクリックすると,次の画面で請求金額が表示されるというわけです。HTMLフォームのコードはリスト1[拡大表示],HTMLフォームに呼び出されるスクリプトbillans.phpはリスト2[拡大表示]のようになっています。このアプリケーションをオブジェクト指向プログラミングで書き直してみましょう。

ポイント1
newでオブジェクトを生成
メソッドは->を付ける

 オブジェクト指向プログラミングでは,関数と変数をセットにした「クラス」という部品を定義します。通常の関数を実行させたい場合は,ただ単に関数名( );などと書くだけでしたが,クラス内部に定義された関数(メソッドと呼ぶ)を使いたい場合は,new演算子を使って,クラスのインスタンス(オブジェクト)を生成する必要があります。

 例えばリスト3[拡大表示]は,クラスEmpを定義したコード(1)とクラスEmpを利用した処理(2)からなるPHPスクリプトです。このスクリプトを実行すると,「こんにちは日経太郎」と表示します。

 クラス定義のコードを見てください。class クラス名{ ~ }の中に,変数が一つ,メソッドが三つありますね。変数の前には必ずvarを付けます(3)。var $変数名 = 100;などと初期値を設定することもできます。

 メソッドの記述は関数と同じでfunction 関数名{ ~ }と書きます。クラス名と同じ名前のメソッド(4)はコンストラクタと呼び,オブジェクトが生成されると自動実行します。クラス内部で宣言した変数を使う場合は,$this->を変数の前に付けます(5)。

 (6)が,クラスEmpからオブジェクト$empを生成するコードです。メソッドは,オブジェクト名に->を付けて使います。つまり(7)は,オブジェクト$empのメソッドset_nameを引数「日経」で実行し,(8)は,メソッドget_nameを実行して変数$nameに格納された「日経太郎」という文字列を出力しているわけです。

ポイント2
クラスにするとわかりやすくなる

 では,リスト3と同じようにしてリスト2をオブジェクト指向スタイルに書き直してみましょう。といっても,何をクラスで書くべきか迷いますよね。ここはあまり難しく考えないで,スタンダード,アドバンスの二つのコースをそれぞれクラスとして定義することにします。また,リスト2では,各コースの計算方法がわかりにくかったので,計算用のメソッドをcalbill( ),基本料金の変数名を$kihon_charge,1分当たりの料金を$min_rate,コース名を$crs_nameとします。こうして書き直したのがリスト4[拡大表示]です。

 コース別にStd,Advの二つのクラスを定義しています。基本料金や計算方法の違いがリスト2よりわかりやすくなっていますね。また,リスト2ではswitch文で処理を分岐しましたが,ここでは,HTMLフォームから送られた文字列($_POST['crs']に格納された値)をそのままクラス名にしているのがミソです(4)。これにより,どのコースを選択しても,(5)のようにオブジェクト$objのメソッドcalbill( )で計算できます。将来,料金コースが増えても,新しいクラスを定義するだけで,switch文を書く必要がないわけです。

ポイント3
一度書いたコードはもう書かない

 リスト4には重要なポイントがもう二つあります。一つは,クラスAdvがクラスStdを「継承」しているという点です。クラスStdが親,Advが子供の関係にあると考えればいいでしょう。このような場合,クラスAdvをサブクラス,継承元のStdをスーパークラスと呼びます。継承は(1)のように,

class サブクラス名
extends スーパークラス名

と記述します。

 継承のメリットは,スーパークラスが定義している変数やメソッドをそのまま利用あるいは上書きできることです。リスト4では,クラスAdvが,calbill( )メソッドの計算方法をクラスStdと異なるものに上書きしています(2)。

 ポイントの二つ目は,その上書きの内容です。(3)のparent::calbill( )というのは,(親クラスである)Stdクラスのcalbill( )メソッドを呼び出すという意味です。::を使うと,new演算子を使わなくてもクラスのメソッドを実行することができるのです。これによりクラスAdvのcalbill( )メソッドは,いったんStdクラスのcalbill( )メソッドで計算したあと,それに1.2を乗算していることがわかるでしょう。

ポイント4
クラス定義は別ファイルにしよう

 リスト4では,一つのファイルの中にクラス,サブクラスの定義,そして,クラスを利用する処理のコードを記述しました。短いスクリプトならこれでも問題ありませんが,コードが長くなってくると見通しが悪くなります。また,せっかくクラスという「部品」にしたのに,処理コードと同一では再利用性も劣りますよね。

 そこで,スクリプトの/安全性やメンテナンス性確保から,クラスの定義とそれを利用するスクリプトは,別ファイルにしたほうがいいでしょう。その場合,クラスを利用するスクリプトでは,コードの冒頭でrequire_once('クラスを定義したスクリプト・ファイル名');と書きます。

(真島 馨=日経ソフトウエア)

(次回に続く)