PHPプログラミング診断室

第4回 郷に入っては郷に従え(治療編)

この記事を読むのに必要な時間:およそ 3.5 分

治療ポイント1. コメントをPHPDocに変更

コメントを記号で彩られた元の形からPHPDocに変更しました。これによりグッと今っぽいPHPコードになったのではないでしょうか。コメントは動作には影響しないものですが,コードを読むという意味ではとても大きな役割を果たします。

PHPDoc形式で書かれたコメント部分をDocBlockと言います。下記がaddItem()メソッドのDocBlockとなります。DocBlockにある@paramタグはメソッドの引数を表しており,addItem()メソッドには,string型の$itemCodeとinteger型の$countの2つの引数があることがわかります。また,戻り値を表す@returnタグがないので,このメソッドには戻り値がないことがわかります(戻り値がない場合は,@return voidと表記する場合もあります)⁠

    /**
     * 商品を追加する
     *
     * @param string $itemCode
     * @param integer $count
     */
    public function addItem($itemCode, $count)

phpDocumentorというAPIリファレンスを自動生成するツールでこのPHPファイルのリファレンスを生成した例が下記です。

phpDocumentorで出力した例

phpDocumentorで出力した例

先ほどのaddItem()メソッドの個所を抜粋しています。DocBlockに記述したコメントやタグが見やすい形式で出力されています。このようにPHPDoc形式でコメントを書くことでこういったツール群の恩恵を受けることができます。

治療ポイント2. ハンガリアン記法からの脱却,メソッド名の見直し

変数名を修正して,ハンガリアン記法から意味のわかりやすい英単語の組み合わせにしました。$a_Item はアイテムが複数であることを示すように$itemsへ,$cGoodsCodeは商品を示す単語をitemに統一して$itemCodeへ,$iGoodsNumも同様に$itemCountへ変更しています。

無駄なプレフィックスがなくなったことで,変数名だけを見ても何を意味するかが明確になり,理解しやすくなっています。前項のPHPDocによるコメントを付けたことで,引数やメンバ変数のデータ型はコメントとして記述しています。

メソッド名についても読みやすいように変更を行いました。いくつかのメソッドではdo_add_item()のように先頭に「do_」が付いていたのですが,これは不要なので削除しています。またPSR-1注1に従い,アンダースコア区切りではなく,camelBack記法に変更したので,addItem()としています。

注1
PHP標準のコーディング規約

治療ポイント3. 配列の操作を修正

配列を格納する変数の初期化では,下記のように[]を代入するようにしました。PHPDocにより,この変数に格納するのは配列であることが明示されていますが,正しい初期値を入れることで,そのことがよりわかりやすくなっています。

    protected $items = [];

次に配列を順に参照する処理をwhile文からforeach文に変更しています。これで添字の抜けなどを考慮せずに,配列の全要素を参照することができます。

        foreach($this->items as $v) {
            $total += $v;
        }

治療ポイント4. PHPセッションの利用

実は,今回の治療で最も大きな変更となったのが,この点です。

ショッピングカートに追加した商品情報(商品コード,個数)は,一時情報としてセッションに保持するのが一般的です。元のコードでは,セッション機能を自作しており注2)⁠セッションIDの生成から,Cookieへの埋め込み,セッション値のデータベースからの読み取り,書き込みなどが実装されています。セッション機能は機能面だけではなく,セキュリティ面についても配慮して実装する必要があり,これはなかなか骨の折れる作業です。

現在のPHP(PHP 4以降)では,標準でセッション機能があるので,こうした自作をする必要はまったくありません。そこで,PHPのセッション機能を使うように変更しました。

まず,セッションから商品情報を読み込む処理ですが,26行目から始まるコンストラクタでこの処理を行っています。$_SESSION変数を参照して,商品情報が存在すれば,メンバ変数$itemsに代入しています。$_SESSION変数は,セッション情報を操作するスーパーグローバル変数で,セッションの値はすべてこの変数に格納されています。つまり,この変数を参照することでセッション情報を読むことができます。

        if (empty($_SESSION[static::SESSION_KEY])) {
            $this->items = [];
        } else {
            $this->items = $_SESSION[static::SESSION_KEY];
        }

次に,セッションへ商品情報を書き込む処理は,77行目のsave()メソッドで行っています。単に$_SESSION変数にメンバ変数$itemsの値を代入しているだけです。これによりセッションへ商品情報が格納されます。save()メソッドは,addItem()deleteItem()など商品情報を操作する各メソッドから呼び出されるので,商品情報の内容が変化した場合は都度セッションの内容も更新されるようになっています。

        $_SESSION[static::SESSION_KEY] = $this->items;

このようにPHP標準のセッション機能を利用すれば,$_SESSION変数を操作するだけで簡単にセッションを扱うことができます。セッションID生成や,Cookieへの埋め込み,期限切れデータの削除(GC)など自分で実装するにはひと手間がかかる部分もPHPが面倒を見てくれます。PHPでセッションを使う場合は,標準のセッション機構を利用しましょう。

注2
PHP 3には標準ではセッション機能はありませんでした。

治療を終えて

今回は,PHP 3の時代に実装されたクラスについて診断を行いました。診断したCartクラスは,ショッピングカートというお馴染みの内容で仕様がイメージしやすいものでした。また,コードの書き方に問題点はありましたが,メソッドなどは,ある程度適切に分けられていたので,その点については理解しやすいコードでした。

治療後の修正コードですが,まだ改良の余地があります。より良いコードにすべく考えてみてください。

  • セッション操作を行うクラスを作り,そのインスタンスを使ってセッション操作を行う
  • getTotalCount()メソッドを,PHPの標準関数を使って1行で実装する
  • Acme\NotFoundExceptionクラスは別ファイルにする

今回はここまでです。また次回の診断でお会いしましょう。

診断を要するPHPプログラム大募集!

本連載では,みなさんからのPHPコードの提供を募集しています。仕事の現場で実際に目撃したり,若気の至りで生み出した秘蔵のお宝コードなどをぜひ投稿してください。 採用された方にはQUOカード3,000円分を差し上げます。応募はこちらのページから。

著者プロフィール

新原雅司(しんばらまさし)

1×1株式会社 代表取締役

大阪でPHPを駆使してWebシステムの開発を行う日々。MotoGPをこよなく愛す。愛車はPCX。

Twitter:shin1x1
blog:Shin x blog

コメント

コメントの記入