カテゴリー別アーカイブ: ファイル処理

PHP spl_autoload_register

久々のPHPネタ.

PHPでは, クライアントサイドJavaScriptと異なり, 必要なモジュールをrequire_onceなどで簡単に読み込むことができます.

しかしながら, モジュールが必要となるたびに読み込むのは少々めんどくさいです.

クラスファイル (クラスが定義されているファイル) の読み込みに限定されますが, 未定義のクラスが使われていると, あらかじめ登録されている規則にしたがって, 自動的にクラスファイルを読み込むという便利な機能を実現するのが, sql_autoload_register関数です.

使い方はこんな感じです.

1. クラスファイルを読み込むメソッドの実装 (loadClassメソッド)

まずは, このメソッドを実装する必要があります. このメソッドの引数には, 必要となったクラス名の文字列が自動的にわたされます.

そして, サンプルコードの実装では, 引数で渡されたクラス名のフィルが指定されたディレクトリ以下にあるかを探索し, 見つかればそのファイルを読み込みます.

2. spl_autoload_registerへの登録

あとは, spl_autoload_register関数を利用して, 未定義のクラスが見つかったら, このメソッドを実行してくださいね〜という指示をしておきます. 引数は配列で, サンプルコードではClassLoaderインスタンスのloadClassメソッドを実行するように定義しています.

ClassLoaderの使い方はこんな感じです.

 $classLoader = new ClassLoader([
     __DIR__ . '/controllers',
     __DIR__ . '/models',
     __DIR__ . '/utils'
]);

この例だと, 未定義のクラスが見つかれば, controllers, models, utils以下のディレクトリを探して〜ということを意味しています.

SplFileObjectとLimitIterator

PHPでログファイルなど巨大なファイルサイズを読み込む場合, file関数やfile_get_contentsなどでぜんぶ読み込んでしまうと, memory_limitにひっかかってエラーが発生してしまうことがあります.

解決策としては, ファイルの必要な部分だけ読み込むことで, そのためには, fopen / fgets or fread / fclose などC言語由来の低レイヤーなAPIを使うというのが1つの方法ですが,  高レイヤーなAPIを利用して解決することもできます.

それが, SplFileObjectクラスとLimitIteratorクラスを利用する方法です. 使い方はこんな感じです

<?php

    $splFileObject = new SplFileObject('ファイルのパス');

    //どっから読み込むか
    $offset = 1000;   //1000行目から

    //どれだけ読み込むか
    $count = 1000;  //1000行分

    $contents = [];

    //1000行目から1999行目まで読み込む
    foreach (new LimitIterator($splFileObject, $offset, $count) as $content) {
        //指定した範囲だけ行ごとに配列の要素として格納する
        //行番号がわかるように$offsetから格納
        $contents[$offset++] = $content;
    }

    var_dump($contents);

ちなみに, 指定した行数を読み込む前に, ファイルの終端に達してもエラーは発生しないので安心してください.