Symfoware

Symfowareについての考察blog

PHP pharに同梱したプログラムにautoloadを適用する

PHPのソースファイルをpharにまとめる方法を調べました。
PHP pharで複数のソースファイルを1つのファイルにまとめる

また、autoloadを自前で実装する方法を調べました。
PHP spl_autoload_registerでautoloadを自前で実装


これらを組み合わせて、pharで固めたソースファイルに対し、
autoloadが適用されるようにしてみます。



サンプルプログラム



pharにするサンプルプログラムは、
PHP spl_autoload_registerでautoloadを自前で実装
こちらで作成したソースにしました。

702_02.png


・classes/Fuga.php


  1. <?php
  2. // classes/Fuga.php
  3. class Fuga {
  4.     
  5.     public function call() {
  6.         echo 'Fuga!'.PHP_EOL;
  7.     }
  8.     
  9. }




・classes/Hoge.php


  1. <?php
  2. // classes/Hoge.php
  3. class Hoge {
  4.     
  5.     public function call() {
  6.         echo 'Hoge!'.PHP_EOL;
  7.     }
  8.     
  9. }




・classes/SomeOne.php


  1. <?php
  2. // classes/SomeOne.php
  3. class SomeBody {
  4.     
  5.     public function call() {
  6.         echo 'SomeBody!'.PHP_EOL;
  7.     }
  8.     
  9. }




・classes/SpecialPiyo.php


  1. <?php
  2. // classes/SpecialPiyo.php
  3. class Piyo {
  4.     
  5.     public function call() {
  6.         echo 'Piyo!'.PHP_EOL;
  7.     }
  8.     
  9. }





目標は
・これらのソースを「my.phar」というファイルにまとめる。
・require_once('phar://my.phar')するだけで、すべての同梱されているクラスがnewできるようにする





pharの作成



こちらを見ながらpharの作成を思い出してみます。
PHP pharで複数のソースファイルを1つのファイルにまとめる


単純にpharにするだけなら、このようなプログラムを用意すればOKです。

・makePhar.php


  1. <?php
  2. // my.pharという名前でpharを作成
  3. $phar = new Phar('my.phar');
  4. // ファイルを追加
  5. $phar->addFile('classes/Fuga.php');
  6. $phar->addFile('classes/Hoge.php');
  7. $phar->addFile('classes/SomeOne.php');
  8. $phar->addFile('classes/SpecialPiyo.php');




実行時に指定するiniファイル
・phar_make_php.ini


[Phar]

phar.readonly = Off
phar.require_hash = Off




以下のコマンドを実行して、pharを作成します。


$ php -c phar_make_php.ini makePear.php




出来上がったmy.pharが使えるかテスト

・sample.php


  1. <?php
  2. require_once('phar://my.phar/classes/Hoge.php');
  3. $hoge = new Hoge();
  4. $hoge->call();




ここまではうまく行きました。


$ php sample.php
Hoge!








pharをrequireした時に呼び出される関数



こちらが参考になりました。
Pharに自作スタブをセットする

・何も指定しないとデフォルトのスタブが設定される
・setStubで独自の内容に書き換えられる

動作を確認してみます。
先ほどのpharを作成するプログラムを変更。


・makePhar.php


  1. <?php
  2. // my.pharという名前でpharを作成
  3. $phar = new Phar('my.phar');
  4. // ファイルを追加
  5. $phar->addFile('classes/Fuga.php');
  6. $phar->addFile('classes/Hoge.php');
  7. $phar->addFile('classes/SomeOne.php');
  8. $phar->addFile('classes/SpecialPiyo.php');
  9. // 独自のstubを設定
  10. $phar->setStub('<?php
  11. echo "stubが呼び出されました。\n";
  12. __HALT_COMPILER();
  13. ');




pharを再作成


$ php -c phar_make_php.ini makePear.php




pharファイルをrequireしてみます。

・sample.php


  1. <?php
  2. require_once('phar://my.phar');





実行すると、setStubしたソースが実行されます。


$ php sample.php
stubが呼び出されました。




setStubにautoloadの設定プログラムを記載すれば、

・require_once('phar://my.phar')するだけで、すべての同梱されているクラスがnewできるようにする

という目標が達成できますね。


ここで作成したローダーをstubに指定します。
PHP spl_autoload_registerでautoloadを自前で実装


・makePear.php


  1. <?php
  2. // my.pharという名前でpharを作成
  3. $phar = new Phar('my.phar');
  4. // ファイルを追加
  5. $phar->addFile('classes/Fuga.php');
  6. $phar->addFile('classes/Hoge.php');
  7. $phar->addFile('classes/SomeOne.php');
  8. $phar->addFile('classes/SpecialPiyo.php');
  9. // 独自のstubを設定
  10. $phar->setStub('<?php
  11. class MyClassLoader {
  12.     private static $_classMap = null;
  13.     
  14.     public static function initialize() {
  15.         // コストの高い対応表の作成処理
  16.         self::$_classMap = array(
  17.             "Hoge" => "Hoge.php",
  18.             "Fuga" => "Fuga.php",
  19.             "Piyo" => "SpecialPiyo.php",
  20.             "SomeBody" => "SomeOne.php",
  21.         );
  22.     }
  23.     
  24.     // spl_autoload_registerに登録する関数
  25.     public static function loadClass($className) {
  26.         echo "load:".$className.PHP_EOL;
  27.         
  28.         $fileName = self::$_classMap[$className];
  29.         
  30.         // ファイルの存在チェック
  31.         $path = "phar://" . __FILE__ . "/classes/".$fileName;
  32.         if (!is_file($path)) {
  33.             echo "load:".$className." error".PHP_EOL;
  34.             return;
  35.         }
  36.         require_once($path);
  37.     }
  38.     
  39. }
  40. // 事前に対応表を作成
  41. MyClassLoader::initialize();
  42. spl_autoload_register(array("MyClassLoader", "loadClass"));
  43. __HALT_COMPILER();
  44. ');




注意点として、ファイルの存在チェックはpharからのパスで行うことになります。
pharのファイル名は「__FILE__」で取得できるので、


  1. "phar://" . __FILE__ . "/classes/".$fileName;



のようにしてis_fileすればファイルの存在チェックが行えます。
pharを再作成してサンプルプログラムを実行。


・sample.php


  1. <?php
  2. require_once('phar://my.phar');
  3. $hoge = new Hoge();
  4. $hoge->call();




狙いの動作になりました。


$ php sample.php
load:Hoge
Hoge!







stubを別ファイルで準備する



setStubでプログラムのソースを文字列で指定するのは、
コードのハイライトも行われず作成が面倒です。

この部分だけ別ファイルに切り出しましょう。


・stub.php


  1. <?php
  2. class MyClassLoader {
  3.     private static $_classMap = null;
  4.     
  5.     public static function initialize() {
  6.         // コストの高い対応表の作成処理
  7.         self::$_classMap = array(
  8.             "Hoge" => "Hoge.php",
  9.             "Fuga" => "Fuga.php",
  10.             "Piyo" => "SpecialPiyo.php",
  11.             "SomeBody" => "SomeOne.php",
  12.         );
  13.     }
  14.     
  15.     // spl_autoload_registerに登録する関数
  16.     public static function loadClass($className) {
  17.         echo "load:".$className.PHP_EOL;
  18.         
  19.         $fileName = self::$_classMap[$className];
  20.         
  21.         // ファイルの存在チェック
  22.         $path = "phar://" . __FILE__ . "/classes/".$fileName;
  23.         if (!is_file($path)) {
  24.             echo "load:".$className." error".PHP_EOL;
  25.             return;
  26.         }
  27.         require_once($path);
  28.     }
  29.     
  30. }
  31. // 事前に対応表を作成
  32. MyClassLoader::initialize();
  33. spl_autoload_register(array("MyClassLoader", "loadClass"));
  34. __HALT_COMPILER();




pharを作る際は、file_get_contentsで取得してやるとOKです。

・makePear.php


  1. <?php
  2. // my.pharという名前でpharを作成
  3. $phar = new Phar('my.phar');
  4. // ファイルを追加
  5. $phar->addFile('classes/Fuga.php');
  6. $phar->addFile('classes/Hoge.php');
  7. $phar->addFile('classes/SomeOne.php');
  8. $phar->addFile('classes/SpecialPiyo.php');
  9. // 独自のstubを設定
  10. $phar->setStub(file_get_contents('stub.php'));



関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2016/08/03(水) 22:19:10|
  2. PHP
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
<<CodeIgniterで大量データを高速に登録する方法の検討 | ホーム | PHP spl_autoload_registerでautoloadを自前で実装>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://symfoware.blog68.fc2.com/tb.php/1906-2f541918
この記事にトラックバックする(FC2ブログユーザー)