PHPフレームワークの基礎勉強、、autoloadって何がいいの?適当にまとめてみた
PHPのフレームワーク内部で使わているautoload処理 これって実際どうなってるの?使うメリットあるの?それにパフォーマンスは?とか 思ったりすると思います!(特にないかもしれません)
今回は、人に説明する時調査しなおした内容も含めてまとめてみたいと思います。
まずは、メリットはあるのか?の説明と、autoloadの処理についての説明も
こんなプログラムをかいていませんか?
<?php require('./hoge.php'); $hoge = new Hoge(); echo $hoge; ?>
よくあるrequireして、インスタンス作成して実行って流れなんですけど ソースコードの量が増えてきたとき、requireするclassの量が増えてきたとき すんんんんんごいめんどいですよね
<?php require('./hoge1.php'); require('./hoge2.php'); require('./hoge3.php'); require('./hoge4.php'); $hoge = new Hoge(); echo $hoge; ?>
こんな感じで、、、めんどい! それにフレームワークとかだと、他のコード内ですでに定義済みなのかとか分からない。。 にじゅう requireはおこられちゃう。。
そんな時にautoloadが大活躍
作成するファイルは test.php TestClass.php の二つです。
1 <?php 2 function autoload($className) { 3 $chunks = explode('_', 'Dummy_Sample_Class_Name'); 4 $path = implode('/', $chunks); 5 if ( is_readable($path) ) {} 6 echo "未定義の[$className]が呼び出されたので、autoloadイベントが発火 \n"; 7 require('./'.$className.'.php'); 8 } 9 spl_autoload_register('autoload'); 10 11 12 echo "未定義クラスのインスタンスを作成すると\n"; 13 $sample = new TestClass(); 14 echo "\n"; 15 echo $sample->disp(); 16 echo "\n"; 17 echo "定義済みクラスのインスタンスを作成すると\n"; 18 $sample = new TestClass(); 19 echo $sample->disp(); 20 echo "\n"; 21 echo "テスト完了"; 22 ?> 23
TestClassは、TestClass.phpに記述
1 <?php 2 class TestClass { 3 public function __construct() { 4 echo __CLASS__ , "インスタンス作成実行"; 5 } 6 7 public function disp() { 8 return __CLASS__."の".__METHOD__."を実行"; 9 } 10 } 11 echo "TestTestクラスの定義完了";
ではでは実行してみます。
$ php test.php 未定義クラスのインスタンスを作成すると 未定義の[TestClass]が呼び出されたので、autoloadイベントが発火 TestTestクラスの定義完了TestClassインスタンス作成実行 TestClassのTestClass::dispを実行 定義済みクラスのインスタンスを作成すると TestClassインスタンス作成実行TestClassのTestClass::dispを実行 テスト完了
こんな感じでrequireしてないファイルのクラスを実行したときに、autoloadイベントが発火して、requireをしてくれます。 そのおかげで、requireをなんども書いたりする必要がなくなりました。
こんな感じで、説明は手抜き感満載ですが、autoloadの仕組みを纏めました。
つぎは、動きとメリットはわかったけど、、パフォーマンスはどうなのよホントのところ!!
ではでは、パフォーマンスの程を 検証方法は、100000ファイルがそれぞれ1つのクラスをrequireして、実行したらどれくらいのパフォーマンスが出るのか!! をやってみたかったのですが、ちょっと準備があれなので
100000回ループを回して、require -> new -> 実行を行うという事を検証しました。
requireを毎回するバージョン
<?php for($i=0;$i<100000;$i++){ require_once('./TestClass.php'); $sample = new TestClass(); $sample->disp(); } echo 'Memory: '.memory_get_usage()."\n";
autoloadでrequireをするバージョン
<?php function autoload($className) { require('./'.$className.'.php'); } spl_autoload_register('autoload'); for($i=0;$i<100000;$i++){ $sample = new TestClass(); $sample->disp(); } echo 'Memory: '.memory_get_usage()."\n";
では実行
まずは、requireするするバージョン
$ time php require_once.php Memory: 670080 real 0m1.427s user 0m0.597s sys 0m0.816s
ぶむふむ では次
$ time php autoload.php Memory: 672784 real 0m0.195s user 0m0.177s sys 0m0.015s
め、、めっちゃ早い!!
ま、そうですよね、毎回requireを実行してる分重たいですよね。。
今回のテストでは異常な差がでましたが、 フレームワークなどで様々なcontroller,modelが同じLibraryや、Exceptionファイルなどをrequireする事はよくよくある事だと思います。 そんな時は、この結果とまではいかないものの、requireコストがかかってしまっているので、autoloadを使うと無駄な読み込みがへるよって話。。
追伸:大抵のフレームワークでは、autoloadの仕組みは標準で備わっているため、意識することがすくないかもしれません笑
以上、大雑把なてきとう解説、てきとうテストでした。