[PHP] 自動require及びincludeをする方法(spl_autoload_register)


Study / PHP    作成日付 : 2020/02/05 03:00:00   修正日付 : 2020/02/05 03:00:00

こんにちは。明月です。


全樹でrequireとincludeに関して説明したことがあります。

link - [PHP] requireとinclude、そして「@」の使用方法


筆者が考えてPHPでプログラミングする時に、一番不便なことがrequireとinclude宣言です。

小さいプロジェクトならそんなに不便とは感じられない可能性もありますが、大きいプロジェクトなら様々なところでクラスを呼出すし関連ページを全て呼び出さなければならないので、すごく大変になるでしょう。

JavaやC#の場合はパッケージ単位、namespace単位で宣言します。それでもソースの上にimportやusingキーワードが多くなることがあります。

まして、クラス単位であるPHPページならすごく多くなるでしょう。

筆者は以前に参加したプロジェクトでrequireだけで何百行目になったことも見たことがあります。


これを解決する関数で「spl_autoload_register」ということがあります。実はこの関数はPHP 5.3から提供していますが、筆者の場合は「7.0」から認識しました。

それで以前にはPHPの場合はパッケージ管理が難しいという認識がありましたが、実はそれじゃなかったんです。やはり、ソースパフォーマンスや可読性は開発者の能力の違いですね。言語は以前から提供しましたが。。。

link - https://www.php.net/manual/en/function.spl-autoload-register.php

<?php
  // Classをnewすれば呼出す。
  spl_autoload_register(function($class) {
    try {
      // Classの名前 + ".class.php"の名にファイル名を探す。
      $filename = $class . ".class.php";
      // デバッグ
      var_dump($filename);
      // includeする。ファイルが無い場合、エラーを発生する。
      if(!@include_once $_SERVER ["DOCUMENT_ROOT"] ."/". $filename) {
        throw new Exception("not file");
      }
    } catch ( Exception $e ) {
      // エラーが発生するとバッファクリア
      ob_clean();
      // エラーが内容を表示する。
      echo $e;
      die();
    }
  });
  // requireやincludeなしでClass1とClass2を呼出す。
  $class1 = new Class1();
  $class2 = new Class2();
?>
<!DOCTYPE html>
<html>
  <head><title>title</title></head>
  <body>
    <!-- Class1のrun関数を呼出す。 -->
    <?=$class1->run()?>
    <br />
    <!-- Class2のrun関数の呼出す。 -->
    <?=$class2->run()?>
  </body>
</html>


<?php
  abstract class AbstractClass {
    public function run() {
      return $this->getData();
    } 
    protected abstract function getData();
  }
?>
<?php
  class Class1 extends AbstractClass {	
    protected function getData() {	
      return "This is Class1";
    }
  }
?>
<?php
  class Class2 extends AbstractClass {
    protected function getData() {
      return "This is Class2";
    }
  }
?>


上の例をみれば、ページの中でクラスだけあるファイルは「.class.php」の拡張子で作成しました。これは標準規約じゃなく、私が楽に区分するように決めた規則です。

ソースでspl_autoload_registerの関数以外にはincludeやrequireがありません。でもClass1をインスタンス生成する時(newで割当て)、spl_autoload_registerの関数が呼出してClass1.class.phpファイルを読み込みます。

ここでinclude_onceで読み込みましたので重複読み込みはありません。Class1クラスはextendsキーワードでAbstractClassを経書しました。それで「AbstractClass.class.php」ファイルも読み込みました。


Class2.class.phpの場合は、「AbstractClass.class.php」を読み込んだことがあるので、再読み込みはしません。


Htmlページではrun関数を呼出しました。run関数では派生クラスのgetData関数を呼出しますね。

それでClass1の場合は「This is Class1」、Class2の場合は「This is Class2」という結果が表示されます。

最新投稿