クラスを自動でローディング

MVCフレームワーク

フレームワークでは1つのクラスを1つのファイルで定義します。これらのクラスを呼び出す際はrequire_once()などを用いてファイルを読み込むのですが、クラスを利用するたびに読み込みを行う処理を記述するのは面倒で無駄です。そこで、フレームワーク内のクラスを自動的に読み込む機能を作ります。

PHPではWebサイトのデフォルトのページとして扱われるのが「index.php」であることが多いです。今回作成するMVCフレームワークにおいても、index.phpをトップとして全体の構造を組み立てていきます。
ただし、アプリケーションですのでクライアントからリクエストに応じて動的にページを生成して返します。個々の画面の基になるViewにデータベースのデータを流し込んでレスポンス用の画面を生成し、これをクライアントに送信します。

ではなぜindex.phpを存在させるかといいますと、アプリケーションの起点にするためです。作成するMVCでは、サイトのアクセスは全てindex.phpで受けるようにします。
index.phpにおいてアプリケーション本体のクラスをインスタンス化し、run()というメソッドを実行させます。ということで、アプリケーション本体のrun()メソッドを起点にします。
また、フレームワーク内のクラスを自動的に読み込む機能を作りますと言いましたが、index.phpと連動して、クラスを自動で読み込むための仕組みを用意します。そこで3つのソースファイルを作成していきます。

クラスの自動ローディング機能を実装する

ここではAutoLoaderクラスを作成します。そのクラスには以下のメソッドを定義します。

registDirectory()メソッドオートロード対象のディレクトリをプロパティに登録する。
register()メソッドオートロードにコールバックとしてloadClass()メソッドを登録する。
requireFile()メソッドregister()メソッドによってオートロードに登録されたコールバック。
指定されたファイルを読み込む。

registDirectory()メソッドの定義

オートロード対象のディレクトリのパスを$dirプロパティに配列型式で格納します。

以下のコードでオートロード対象となるディレクトリのパスを登録するメソッドを定義します。

<?php
class AutoLoader {
  protected $_dirs = array();
  
  public function registDirectory($dir){
    //プロパティ$_dirsに配列で格納
    $this->_dirs[] = $dir;
  }
}

register()メソッドの定義

spl_autoload_register()関数を使ってオートロードの仕組みを作ります。

インスタンスのメソッドをコールバックとして登録するには配列を使います。配列の0番目の要素にインスタンス、1番目の要素にメソッド名を指定します。静的メソッドの場合は0番目の要素としてクラス名を指定します。

<?php
class AutoLoader {
  protected $_dirs = array();
  
  public function registDirectory($dir){
    $this->_dirs[] = $dir;
  }

  public function register() {
    //自分自身のrequireFileを登録する
    spl_autoload_register(array($this, 'requireFile'));
  }
}

requireFile()メソッドの定義

オートロードの仕組みとして、登録しておいたディレクトリ内のクラスを呼び出すと、クラス名がコールバックに渡されるようになるので、ここでの処理の手順は以下の通りです。

  1. $_dirsプロパティに格納されているオートロード対象のフォルダーへのフルパスを1個ずつ取り出し、/とパラメータに格納されているクラス名、拡張子を連結してオートロードを行うクラスのパスを生成する。
  2. is_readable()関数で$fileが読み込み可能かどうかを調べ、可能であればrequireクラスを読み込む。

$_dirsプロパティには複数のパスが登録されているので、それぞれのパスに対してクラス名を連結し、読み込み可能であれば読み込みます。

is_readable()関数とはファイルが存在し、読み込み可能か調べる関数です。読み込み可能でTRUE、不可ならFALSEを返します。

is_readable($filename)

クラス名をパラメーターで取得して、require命令で読み込む処理を記述します。上二つのメソッドに続いて記述してください

<?php

class AutoLoader {
  protected $_dirs = array();
  
  public function registDirectory($dir){
    $this->_dirs[] = $dir;
  }

  public function register() {
    //自分自身のrequireFileを登録する
    spl_autoload_register(array($this, 'requireFile'));
  }

  public function requireFile($class){
    foreach($this->_dirs as $dir){//パスを取得する
      $file = $dir . '/' . $class . '.php';//クラスファイルへのパスを生成
      
      if(is_readable($file)) {
        require $file;
        return;//読み込んだらループ終了
      }
    }
  }
}

AutoLoaderクラスのコードまとめ

<?php

class AutoLoader {
//省略
  public function requireFile($class){
    foreach($this->_dirs as $dir){//パスを取得する
      $file = $dir . '/' . $class . '.php';//クラスファイルへのパスを生成
      
      if(is_readable($file)) {
        require $file;
        return;//読み込んだらループ終了
      }
    }
  }
}

オートロードを実行するクラスをインスタンス化

オートロードを実行するAutoLoaderクラスを作成しましたが、クラス自体をインスタンス化しないといけません。
AutoLoaderクラスをインスタンス化してオートロードに登録する処理を行うbootstrap.phpの処理を作成します。
これはルートディレクトリ、起点となるディレクトリに保存します。

<?php
require 'mvc/AutoLoader.php';

$loader = new Loader();//インスタンス化
$loader->registDirectory(dirname(__FILE__).'/mvc');//ディレクトリ登録
$loader->registDirectory(dirname(__FILE__).'/models');

$loader->register();//オートロードに登録

?>

Webプリケーションの起点となるフロントコントローラーを作成

MVCフレームワークでは初め、全てのリクエストを1つのphpファイルで受け取るようにしますので、そのPHPファイルになるindex.phpを作成します。コントローラーの前の段階でアクセスされることになるフロントコントローラー(index.php)を作成します。

<?php
require '../bootstrap.php';
?>

Apache側の設定を行うために.htaccessファイルを配置

全てのアクセスをindex.phpに集中させるためにApacheの設定をしなければいけません。これには、.htaccessファイルを作成し下記のように記述します。

<IfModule mod_rewrite.c>
    RewriteEngine On

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ index.php [QSA,L]

</IfModule>

これで、クラスが呼び出されると、自動でローディングされるようになりました。

コメント

タイトルとURLをコピーしました