関数

PHP・WordPressにおけるrecurse_dirsize()関数を解説:ディレクトリサイズの再帰的取得方法

recurse_dirsize()関数は、PHP・WordPress環境で指定ディレクトリ内の全ファイルやサブディレクトリのサイズを再帰的に計算し、バイト単位で返す機能があります。

除外対象や実行時間制限、キャッシュ管理などのオプションにより、効率的に容量を把握できるようになっています。

関数の基本動作

ディレクトリ検証

存在確認とディレクトリ判定

関数実行前に、最初に対象のパスが存在するかどうかを確認します。

file_exists()関数と is_dir()関数を用いて、指定パスが実在しディレクトリであるかを判定します。

以下は基本的なチェック方法のサンプルコードです。

// $directory には対象となるディレクトリのパスが格納されている
if ( ! file_exists( $directory ) || ! is_dir( $directory ) ) {
    // ディレクトリが存在しない場合、またはディレクトリでない場合は false を返す
    return false;
}
// 対象ディレクトリが存在しなければ false が返される

読み取り権限のチェック

ディレクトリが存在していても、読み取り権限がなければファイルのサイズを正しく取得できません。

そこで、is_readable()関数を利用し、ディレクトリが読み取り可能であるか確認します。

権限不足の場合、処理を中断して適切な値 (例えば false) を返すようにします。

// $directory の読み取り権限があるかチェック
if ( ! is_readable( $directory ) ) {
    // 読み取りが不可能なディレクトリの場合は false を返す
    return false;
}
// 読み取り権限がない場合、ここで処理が中断され false が返される

再帰処理の流れ

ファイルサイズの取得

ディレクトリ内の各ファイルに対して、filesize()関数を用いてバイト単位でサイズを取得します。

ファイルかどうかを判定し、サイズを合計に加算するのが基本の処理になります。

if ( is_file( $path ) ) {
    // ファイルサイズを取得して加算する
    $size += filesize( $path );
}
// 指定されたファイルのサイズがバイト単位で $size に加算される

サブディレクトリの走査

対象パスがディレクトリである場合は、再帰的に同じ関数を呼び出し、内部のサイズも合計していきます。

これにより、入れ子となったディレクトリ構造全体のサイズ計算が可能となります。

if ( is_dir( $path ) ) {
    // 再帰的にサブディレクトリのサイズを計算する
    $dirSize = recurse_dirsize( $path, $exclude, $max_execution_time, $directory_cache );
    if ( $dirSize !== false ) {
        $size += $dirSize;
    }
}
// サブディレクトリ内のファイルサイズが再帰的に合計される

タイムアウト制御

多くのファイルを処理する際に、スクリプト実行時間が長くなることを防ぐため、実行時間を監視し制限時間を超えた場合には処理を中断します。

開始時刻と現在時刻を比較し、指定した秒数を超えた時点で処理を停止する実装となっています。

// WP_START_TIMESTAMP はスクリプトの開始時刻を示す定数
if ( $max_execution_time > 0 && ( microtime( true ) - WP_START_TIMESTAMP ) > $max_execution_time ) {
    // 設定時間を超えた場合、タイムアウトとして中断する
    $size = null;
    break;
}
// 実行時間が制限を超えた場合、処理がタイムアウトで中断される

除外設定とエラー処理

除外パラメータの指定

文字列と配列での指定

サイズ計算から特定のディレクトリやファイルを除外するため、除外パラメータには文字列または配列で対象パスが渡されます。

渡された値と現在のパスが一致するかを比較することで、除外するかどうかを判断します。

// $exclude は除外対象のパス、文字列またはパスの配列
if ( ( is_string( $exclude ) && $directory === $exclude ) ||
     ( is_array( $exclude ) && in_array( $directory, $exclude, true ) )
) {
    // 除外対象の場合は再帰計算を行わず false を返す
    return false;
}
// 除外対象のディレクトリが検出された場合、処理は中断され false が返される

除外対象の処理方法

除外対象に一致する場合、サイズ計算の再帰呼び出しをスキップする処理を行います。

これにより、特定パスのファイルやディレクトリを計算から効率的に除外できます。

比較対象のパスは、絶対パスで指定されるケースが一般的です。

// 除外対象の場合、対象ディレクトリの再帰計算を行わない
if ( ( is_string( $exclude ) && $directory === $exclude ) ||
     ( is_array( $exclude ) && in_array( $directory, $exclude, true ) )
) {
    return false;
}
// 除外設定が有効なディレクトリの場合、計算処理がスキップされ false が返される

エラー発生時の対応

無効パスの場合の処理

指定されたディレクトリパスが無効な場合、エラーとして早期に処理を中断する必要があります。

file_exists()is_dir() のチェックによって、無効なパスは検出され、早い段階で false を返すように実装されています。

if ( ! file_exists( $directory ) || ! is_dir( $directory ) ) {
    // 無効なディレクトリパスの場合、エラーとして false を返す
    return false;
}
// 無効なディレクトリであると判定された場合、false が返される

タイムアウト時の中断

指定された実行時間を超えた場合、タイムアウトとして処理を中断します。

タイムアウトが発生すると、処理結果を信頼できないため、null やエラーメッセージを返す実装が一般的です。

以下のコードは、タイムアウト制御の一例です。

if ( $max_execution_time > 0 && ( microtime( true ) - WP_START_TIMESTAMP ) > $max_execution_time ) {
    // タイムアウトに達した場合、中断して null を返す
    $size = null;
    break;
}
// タイムアウト条件に該当すると、計算処理が中断され null が返される

フィルターフックの活用

pre_recurse_dirsize フィルターの役割

WordPress のフィルターフックを利用することで、既存の処理に対してカスタムな動作を追加できます。

pre_recurse_dirsize フィルターは、ディレクトリサイズ計算前に値を変更するためのフックとして実装されており、独自処理によるサイズ計算を行う場合に役立ちます。

// pre_recurse_dirsize フィルターを利用してサイズ計算をカスタマイズする例
$size = apply_filters( 'pre_recurse_dirsize', false, $directory, $exclude, $max_execution_time, $directory_cache );
if ( false !== $size ) {
    // カスタマイズされたサイズが返された場合は、その値を利用する
    return $size;
}
// カスタムフックで処理が上書きされた場合、そのサイズが返される

コールバックによる値の置換

開発者は独自のコールバック関数を登録して、標準のサイズ計算ロジックの動作を置き換えることができます。

以下は、特定ディレクトリに対して固定値を返すコールバックの例です。

// functions.php あるいはカスタムプラグイン内にコールバック関数を定義する例
add_filter( 'pre_recurse_dirsize', 'custom_dirsize_handler', 10, 5 );
function custom_dirsize_handler( $space_used, $directory, $exclude, $max_execution_time, $directory_cache ) {
    if ( '/var/www/html/wp-content/uploads' === $directory ) {
        // 特定ディレクトリの場合、固定のサイズ値を返す
        return 987654321;
    }
    // 他の場合は、デフォルト値を返す
    return $space_used;
}
// /var/www/html/wp-content/uploads の場合、987654321 バイトが返される

他機能との連携

また、フィルターフックを利用することで、外部のAPIやシステムと連携したサイズ計算が可能となります。

たとえば、CDN やOS純正のツールを用いてディレクトリサイズを取得し、フィルターを通してその結果を反映できる仕組みを構築できます。

キャッシュ管理とパフォーマンス向上

キャッシュの取得と利用

ローカルキャッシュの活用方法

再帰処理中に同一ディレクトリに対して重複した計算を行わないために、ローカルキャッシュを活用します。

キャッシュ配列にすでに計算済みのサイズが保存されているかを確認し、存在する場合はその値を返すことで処理速度を向上させます。

// $directory_cache 配列にキャッシュが存在するかをチェックする
if ( isset( $directory_cache[ $directory ] ) && is_int( $directory_cache[ $directory ] ) ) {
    return $directory_cache[ $directory ];
}
// キャッシュが有効であれば、キャッシュ内のサイズ値が返される

トランジェントAPIとの連携

WordPress のトランジェントAPI を利用して、キャッシュの永続化を行うことも可能です。

計算完了後に set_transient() を用いてキャッシュ情報を保存することで、後続の呼び出し時に再計算の負荷を軽減できます。

// トップレベルの呼び出しでキャッシュを保存する例
$expiration = ( wp_using_ext_object_cache() ) ? 0 : 10 * YEAR_IN_SECONDS;
set_transient( 'dirsize_cache', $directory_cache, $expiration );
// キャッシュされたディレクトリサイズ情報がトランジェントAPIに保存される

実行時間制限の管理

WP_START_TIMESTAMP の利用方法

スクリプト開始時刻を示す WP_START_TIMESTAMP定数を利用して、実行時間を計測します。

開始地点からの経過時間を microtime(true) で取得し、設定した実行時間の上限と比較してタイムアウト判定を実施します。

// スクリプト開始時刻と現在時刻との差を計算して実行時間を管理する
$currentTime = microtime( true );
$elapsedTime = $currentTime - WP_START_TIMESTAMP;
if ( $elapsedTime > $max_execution_time ) {
    // 実行時間超過の場合は中断処理へ移行する
    $size = null;
    break;
}
// 指定された実行時間を超えると、タイムアウトとして処理が中断される

中断条件の設定詳細

タイムアウト条件は、再帰的なディレクトリ走査中に都度確認されます。

環境によっては、各サブループ毎に中断の判定が入るため、細かい制御が可能です。

条件に一致した場合、途中までの計算結果ではなく、null などエラー値を返す設計になっています。

// 各ループ内でタイムアウト条件をチェックする例
if ( $max_execution_time > 0 && ( microtime( true ) - WP_START_TIMESTAMP ) > $max_execution_time ) {
    // 実行時間が上限を超えた場合、中断して null を返す
    $size = null;
    break;
}
// 中断条件に達すると、再帰処理中のループが break され、null が返される

まとめ

この記事では、WordPress環境におけるrecurse_dirsize()関数の基本動作や検証方法、ディレクトリ内ファイルのサイズ取得および再帰処理、タイムアウト制御の仕組みが理解できます。

さらに、除外設定やエラー処理、フィルターフックを活用したカスタマイズ方法、キャッシュ管理と実行時間制限の実装手法が学べる内容となっています。

関連記事

Back to top button
目次へ