min117の日記

初期desireもち。趣味Mac,メインFedora,仕事xp。

PHP 再帰関数その4

f:id:min117:20210102020211p:plain

 

フォルダ階層の再帰関数による読み込み。前回の続き。

min117.hatenablog.com

 

改良して、以下の機能を実装した。

 

読み込んだオブジェクトが

 ファイルの場合は何もしないけど

 フォルダの場合には「Go」ボタンを表示して、押せばさらに下の階層に行けるようにした(というか、そうしたいので、まずはGoボタンだけ表示した)

f:id:min117:20210102004733p:plain

 

現在いる場所(getcwd)の階層($kaisou_now)を関数の引数として受け取るようにした。

f:id:min117:20210102004914p:plain

子フォルダを読み終えて親フォルダに戻る時に階層を1減らすとこの実装が難しいんだけど、子フォルダを読む(再帰する)ときに、今の階層($kaisou_now)を引数で渡せば解決することが分かった。そうすれば、子フォルダに行くときだけ階層が+1されて、戻った時には前の階層数に戻ることができる。

 

読み込む階層の深さ($kaisou_limit)を指定できるようにした。

f:id:min117:20210102004914p:plain

あらかじめ階層の深さ限界($kaisou_limit)を宣言しておいて

$kaisou_nowがそれより深く潜る前にreturn する。

f:id:min117:20210102005719p:plain

$kaisou_limit をユーザーに入力させれば、読み込みたい任意の深さまでのフォルダを辿るようにできる。$kaisou_limitは(再帰された関数インスタンスの)全てから参照されるので、グローバル変数としておく(19行目)。

 

ソース変更による動きの変化はこんな感じ。

f:id:min117:20210102015301g:plain

次回はさらに改良して「Go」ボタン押下でそのフォルダ階層に降りていく処理を実装する。Goボタン(input type="button"のとこ。下のソースの58行目)を押した時に再起関数を呼ぶとこの実装が難しそう。

 

今回のソース全景。

f:id:min117:20210102015706p:plain

f:id:min117:20210102015731p:plain

 

コピペ保存用

<?php

// nikkei XTECK

// 54. 再帰関数を使ってみよう

// https://xtech.nikkei.com/it/article/COLUMN/20070827/280408/

 

// 引数$path にはディレクトリorファイルの絶対パスを指定する。

 

// $saiki = 0;

$kaisou_now = 0;

$kaisou_limit = 2;

 

function getDirList($path ,$kaisou_now) {

    /// 階層を引数で受け取ると、親フォルダに戻った時に正しく階層-1される

    /// global $kaisou;しちゃうと、親フォルダに戻った時に階層+1されバグる

    // global $saiki;

    // global $kaisou_now;

    // $total_size = 0;

    global $kaisou_limit;

    print '<br>';

 

    //指定したのがファイルだった場合はサイズを返して終了

    if (is_file($path)) {

        // print '再帰:' . $saiki . '回目';

        // print '<br>';

        print '<font color="blue">ファイル</font>パス:<br>' . "$path";

        print '<br>';

 

        print '階層:' . $kaisou_now;

        print '<br>';

 

        return filesize($path);

    } elseif (is_dir($path)) {

        // カレントディレクトリ(.)or

        // 上位階層ディレクトリ(..)の場合はここで終了

        $basename = basename($path);

        if ($basename == '.' || $basename == '..') {

            return 0;

        }

 

        // if ($kaisou_now == 3) {

        //     return 1;

        // }

 

        // ファイルでもなく、カレント(.)でもなく、親(..)でもない

        // つまりディレクトリだったら、フォルダpathとして表示

        print '<font color="red">フォルダ</font>パス:<br>' . "$path";

        print '<br>';

 

        // 階層を表示

        $kaisou_now++;

        print '階層:' . $kaisou_now;

        print '<br>';

        print '階層limit:' . $kaisou_limit;

        print '<br>';

 

        print "$obj";

        print '<input type="button" name="someAction" value="Go" /><br>';

 

        if($kaisou_now >= $kaisou_limit) {

            return 0;

        }

        // ディレクトリ内にあるオブジェクト(ファイルまたはディレクトリ)の一覧を入>手。

        $obj_list = scandir($path);

 

        foreach ($obj_list as $obj) {

            ///// ボタンのクリックでphp関数を実行する 

            // https://tutorialmore.com/questions-1286453.htm

            // print '<input type="button" name="' . basename($obj) . '" id="id_' . basename($obj) . '" value="RUN" onclick="' . getDirList($path . '/' . $obj) . '" /><br>';

 

            ///// ↓ これだと、onclick()と書いても、クリックの有無に関係なくgetDirListが読まれてしまう

            // サーバがパースしちゃうから

            // print '<input type="button" name="test" id="test" value="RUN" onclick="' . getDirList($path . '/' . $obj) . '"/><br>';

            // if( is_dir($obj)) {           

            // }

 

            getDirList($path . '/' . $obj, $kaisou_now);

 

            // ディレクトリ内のオブジェクトを引数にして、自分自身を呼び出す再帰

            // getDirList($path . '/' . $obj);

            // $total_size += getDirList($path . '/' . $obj);

            // $objがディレクトリだったら

            // また自分自身を呼び出す(再帰)して…を繰り返して

            // 最深部の階層(ファイルのみが存在する階層)まで行く

        }

        // return $total_size;

        // print '階層ぅ:' . "$kaisou_now" . '<br>';

 

    } else {

        return 0;

    }

}

 

// カレントフォルダの確認

print '------------------------<br>';

print getcwd() . '<br>';

print '階層:' . $kaisou_now;

print '<br>';

print '------------------------<br>';

 

//関数実行

// print getDirList('/media/WD30EZRX/PT3/test_pdf2jpg');

// print getDirList("getcwd()");

// print getDirList("/media/6TB/mp3z");

print getDirList(getcwd(), 0);