PHPオブジェクト指向実践

基本の仕組み構築

「仕組み」を作る

初級編のサンプルでは、処理のメイン部分をクラス化し、オブジェクト指向化しました。
しかし実際のところ、単に処理をクラスという枠の中にそのまま押し込んだだけで、なんとなく目新しさを感じないかもしれません。
「とりあえず」クラスというものを使ってみたっていうレベルにおさまっています。


まず、一番原始的なPHPプログラミングは、HTMLとPHPコードが絡み合い、交錯しているような状態のものです。

そこからもう少し、HTMLとコードの分離を考えた場合、HTMLファイルの先頭部分、つまりタグより上の部分にメインの処理をまとめて書き、処理結果は文字列として変数に保持しておき、HTMLの中ではそれをechoするPHPコードだけ埋め込むような形になります。

次の段階としてオブジェクト指向化を図り、メインロジックはクラスの中に記述し、クラスは別のファイルへ。メインPHPからはクラスファイルをインクルードしてクラスインスタンスを生成してそのメソッドを実行し、結果だけを受け取る、という形。

この時点ではクラスは単なる関数の集合みたいな感じになり、オブジェクト指向っぽさに欠けます。

オブジェクト指向ではその特徴を生かして、構造的に仕組みを作ることで面白味が出てくるんじゃないかと思います。

ここから、一つの例を紹介していきますので、あくまで例と思ってみてみてください。

基礎クラスの作成

まず一つの考え方として、一つのページに対して必ず一つのクラスが関連づいているような形を想定します。単順に、トップページならindex.phpになりますが、これに対してはたとえばIndexProcessクラス、掲示板のページのbbs.phpに対してはBbsProcessクラス、という具合です。

ここでまず、どのページにも共通で行うような処理がないかを考えます。
例えばどのページにおいてもアクセスがあったらカウンターを加算するとか、アクセスログへの記録処理とか、何かあるかもしれません。

そのため、共通処理を抽象クラスに定義し、各ページに対応するクラスはこれを継承するような形にすれば、知らないうちに共通処理が実行されているような構造にしていきます。

抽象クラスは例えばこんな感じです。

SiteProcess
<?php

require_once ROOT . '/system/Counter.php';

abstract class SiteProcess
{    
    protected $data = array();
    
    abstract protected function main();
    
    public function exec()
    {
        try {
            Counter::increment();
            $this->main();
        } catch (Exception $e) {
            die('システムエラーが発生しました');
        }
    }
    
    public function getData($key = null)
    {
        if (null == $key) {
            return $this->data;
        } else {
            return $this->data[$key];
        }
    }    
}

?>

publicメソッドはexecとgetDataです。
execはメインの処理実行、getDataはメイン処理の結果の取得です。
execでやっている事は、カウンターの加算処理と、mainメソッドの実行です。このmainメソッドは抽象メソッドですが、これを継承先で必ず実装して、各ページの特有の処理を記述するためのメソッドです。
継承先ではmainメソッド内に処理を記述すれば、execメソッドの実行により、間接的にmainメソッドの処理が呼ばれる仕組みです。

つまり、基本の流れは、この抽象クラスを継承したクラスを作り、各ページのphpファイルでこのクラスのインスタンスを生成し、固定的にexecメソッドの実行を行うだけです。
何かHTMLに埋め込む値が必要な場合、mainメソッド内でクラスフィールドである$dataにハッシュとして値を入れます。そしてメインスクリプトからgetDataメソッドでこの値が取得できるというわけです。

継承クラスを作る

ではこの抽象クラスであるSiteProcessを継承してトップページの処理クラスを作ってみます。

IndexProcess.php
<?php

require_once ROOT . '/system/SiteProcess.php';

class IndexProcess extends SiteProcess
{
    protected function main()
    {
        // カウンター値取得
        $this->data['counter_value'] = Counter::get();
    }
}


?>

今回はトップページで行う処理はカウンター値の取得処理のみのため、クラスはこれだけのものです。
基礎クラスで共通部分を記述しているため、継承クラスは非常にスッキリします。

そしてこのクラスのインスタンスを生成して処理を実行する、メインスクリプト処理を記述します。

index.php
<?php
define('ROOT', '・・・');
require_once ROOT . '/system/index/IndexProcess.php';
$proc = new @CIndexProcess@()
$proc->exec();
$data = $proc->getData();
?>

<html>
<head>
<title>PHP講座トップページ</title>
</head>
<body>
<h1>PHP講座</h1>
<p>あなたは<?php echo $data['counter_value']; ?>番目の訪問者です</p>

</body>
</html>

まず、クラスファイル等の読み込みは絶対パスで指定したほうが単純なため、ルートディレクトリのパスを定数定義し、このパスを基準にrequire_onceを行うようにします。

そしてクラスインスタンスを生成し、execメソッドを呼び出した後にgetDataメソッドを呼び出すだけです。
この仕組みだと、ページに対応するクラスを必ず作り、メインスクリプトはexecとgetDataを実行するという流れは同じのため、どんなページでもお決まりの記述とすることが出来るのです。