2

私は現在、PHPでフレームワークをプログラミングしています(主に教育上の理由と、時間を渡す方法のため)。そして、ディレクトリツリーを自動的にスキャンしてその中のすべてのクラスを検出し、次の形式で配列を作成するオートローダーを作成しました。

Array(
    'MyAwesomeClass' => 'path/to/file/in/some/subdirectory/MyAwesomeClass.php',
    'MyOtherAwesomeClass' => 'path/to/file/MyOtherAwesomeClass.php'
     // ....
);

最初はこれはとてもきれいでした。クラスをどこに置くか心配する必要がないからです。

しかし、後で私はこれが非常にリソースを大量に消費することを発見しました。そこで、キャッシュメカニズムを作成し、インデックスをシリアル化してファイルに保存しました。これにより、PHPスクリプトの応答時間が少なくとも50%短縮されました。しかし、それはいくつかの問題をもたらしました。

フレームワークの他のクラスでは、私はよく次のようなものを使用します。

class_exists('MyAwesomeClassController');

問題は、新しいクラスを追加した場合MyAwesomeClassController、そのクラスはまだインデックスに含まれておらず、class_existsfalseを返すことです。問題は、フレームワークに新しいクラスを追加するたびに、キャッシュされたファイルを削除する必要があることです(オートローダーにインデックスを再作成させるため)。

私が試したもう1つのこと(少しハッキーです):Autoloaderクラスで、class_exists()を使用してautoloadメソッドが呼び出されたかどうかを確認しました。この場合、インデックスを再作成して、要求されたクラスがどこかにあるかどうかを確認しました。class_existsただし、ほとんど存在しないクラスを使用して呼び出されることがあるため、これもうまくいかないようです。したがって、これは基本的に、すべてのリクエストでインデックスを再作成するのと同じソリューションです。

解決策はありますか?または、オートローダーを完全に書き直す必要がありますか?

4

3 に答える 3

1

私は少し前にこの道をたどり、同じ結論に達しました。つまり、リソース集約型です。ここで実際に行っているのは、ある種のリンカーを構築することです。

名前空間とマップの組み合わせに切り替えました。名前空間をフォルダーにマップすると、オートローダーが呼び出されると、名前空間が削除され、対応するフォルダーが検索され、ファイルが含まれます。

私のマップは次のようになります(形式にxmlを選択します):

<?xml version="1.0" encoding="UTF-8"?>
<autoloader>  
  <namespace id="Ganymedes\Core">/system/core</namespace>
  <namespace id="Ganymedes\Core\Debug">/system/core/debug</namespace>
</autoloader>  

そしてクラスローダー:

  public function ClassLoader( $class )
  {    
    if( class_exists( $class, false ))
      return true;

    $classparts = explode( '\\', $class );
    $classfile = '/' . strtolower( array_pop( $classparts )) . '.php';
    $namespace = implode( '\\', $classparts );

    if( isset( $this->namespaces[$namespace] )) {
      foreach ( $this->namespaces[$namespace] as $path ) 
        if( is_readable( $path . $classfile ))
          include_once $path . $classfile;

      return true;
    }

    return false;
  }    
于 2012-10-12T13:07:00.637 に答える
1

多分私はあなたがやろうとしていることを正しく理解していません...しかし、get_include_path/set_include_path__autoload($class)組み込み関数の何が問題になっていますか?

私のコメントを説明する編集:

「header.php」(すべてのスクリプトの開始時に含まれるファイル):

set_include_path(get_include_path().PATH_SEPARATOR."my/first/directory"
                                   .PATH_SEPARATOR."my/second/directory"
                                   .PATH_SEPARATOR."this/is/another/directory"
                                   ...
                                   .PATH_SEPARATOR."and/here/is/the/last/one");

function __autoload($class) {
    require_once($class.".class.php");
}

オートロード機能は、必要なファイルが見つかるまで、パス内の各ディレクトリをチェックします。パフォーマンスをチェックしたことはありませんが、何百ものディレクトリがない限り、それほど重要ではないと思います。整理されている場合は、頻繁に使用する (基本) クラスを最初の「余分な」パスに配置して、すぐに見つけられるようにすることができます。

オンラインの PHP マニュアルで、__autoload は推奨されなくなり、代わりに spl_autoload_register を使用する必要があることに気付きましたが、概念は同じです。

于 2012-10-12T13:09:26.880 に答える
1

ロードしようとしているクラスが常に存在する必要があるという前提の下で、オートローダーは次のことを実行できます。

  1. (キャッシュされている) マップ内のクラス名を検索します。存在する場合は、ファイルをロードします。

  2. 存在しない場合は、別のスキャンを実行し、新しく生成されたマップでクラス名を検索します。存在する場合は、新しいマップをディスクに書き込み、ファイルをロードします。

  3. それでも存在しない場合は、アラームを発生させます。

3 番目のステップは、ネガティブ キャッシュを導入することでも改善できます。クラスがそのマップに存在する場合、以前の試行に基づいてクラスが存在しないことがわかります。ネガティブ キャッシュの寿命は短くなりますが、サーバーが破壊されないようにするのに十分な長さです。

展開システムの一部としてキャッシュをオフラインで作成することも検討できます。

于 2012-10-12T14:12:02.067 に答える