laravelの勉強をしていて、spl_autoload_register()と言うファンクションの存在を知った。
うまく使えば便利そうだなーと思う反面、使い方の理解にはちょっと苦労したファンクションなので、学んだことをメモ。
spl_autoload_registerとは?
phpでは以下のように、未定義のクラスを使用する場合、エラーとなる。
$class1 = new Class1();
=> PHP Fatal error: Uncaught Error: Class 'Class1' not found in test.php:3
Class1()を定義していない、
もしくは定義しているファイルをrequireしていないのでエラーになるのは当然である。
しかし、spl_autoload_registerを使用することにより、
未定義のクラス使用でエラーとなる前に、最後の救済メソッドとして登録しておいたメソッドの実行が可能となる。
この救済メソッドに、未定義のクラスを探しにいく処理を書いて置くことで、上記のようなエラーを回避することができる。
spl_autoload_register(救済メソッド($class)(
未定義のクラス($class)を探しに行く処理
))
$class1 = new Class1(); //救済メソッドが実行される
=> Class1をnewできる
spl_autoload_registerの使い方
ではspl_autoload_registerの使い方を解説して行く。
spl_autoload_registerの書式
まずは書式から。
書式自体は簡単で、引数に救済メソッドとなるコールバック関数※を記述するだけ。
このメソッドが、未定義のクラスを使用する際に呼び出されることとなる。
spl_autoload_register(コールバック関数);
spl_autoload_registerの使い方例
まずは以下のようなディレクトリ構成があるとする。
Class1.phpとClass2.phpにはそれぞれClass1とClass2と言うクラスが定義してある。
そして、test.phpから上記のファイルをrequireせず、spl_autoload_registerを使ってクラスを使用すると言う状況を例にする。
/
├── dir1
│ └── Class1.php //Class1と言うクラスが定義済み
├── dir2
│ └── Class2.php //Class2と言うクラスが定義済み
└── test.php
test.php
test.php
<?php
class ClassLoader
{
■ 救済メソッド実行時、クラス探索の対象となるディレクトリを格納する変数
protected $dir;
■ 救済メソッド実行時、クラス探索の対象となるディレクトリを保存する関数
public function registerDir($dir)
{
$this->dirs[] = $dir;
}
■ spl_autoload_register実行
public function register()
{
■ 未定義のクラスをcallした際、loadClassメソッドを実行する。
spl_autoload_register(array($this, 'loadClass'));
}
■ 救済メソッド。引数には、callしようとしたクラス名が渡ってくる。
public function loadClass($class)
{
■ 登録済みの探索ディレクトリに、newしようとしたクラスファイルが存在しているか確認
foreach($this->dirs as $dir){
$file = $dir. '/' . $class . '.php';
■ 存在していればrequire。エラーにならない。
if(is_readable($file)){
require $file;
return;
}
}
}
}
$loader = new ClassLoader();
dir1とdir2をクラス探索対象のディレクトリに登録
$loader->registerDir(dirname(__FILE__).'/dir1');
$loader->registerDir(dirname(__FILE__).'/dir2');
spl_autoload_register実行
$loader->register();
requireしていないクラスをnewする。newに成功する。
$Class1 = new Class1();
$Class2 = new Class2();
test.phpを実行すると、処理の最後に記述している通り、Class1とClass2のnewに問題なく成功する。
事前にdir1とdir2を、registerDirメソッドで探索対象として登録しておき、
その後spl_autoload_registerを実行、loadClassメソッドを救済メソッドとして登録している。
結果、Class1とClass2のnewの際、当然クラス定義が見つからないため、最後の救済メソッドとしてloadClassメソッドが実行され、無事、探索ディレクトリ内のdir1とdir2からクラスが見つかったと言う流れだ。
spl_autoload_registerを使用することのメリット
spl_autoload_registerを使用することのメリットは以下のようなことが挙げられる。
普段あたり前に書いているrequireの記述だが、規模が大きくなるとそれだけ記述量も増え、何かあったときのメンテナンス性が損なわれたり、可読性が落ちてしまうなどのデメリットがあるため、それらを解消することができると言うメリットがある。
spl_autoload_registerとの関連記事
spl_autoload_registerが理解できたならば、合わせて以下の記事も読むとより、laravelやphpの理解が深まると思うのでぜひ合わせて読んでいただきたい。
https://www.php.net/manual/ja/function.spl-autoload-register.php
コールバック関数に関しては以下記事にて詳しく説明。参考までに。