• ベストアンサー
  • 暇なときにでも

PHP初心者 再帰処理について

あるフォルダ以下に含まれる全てのフォルダ名をフルパスですべて列挙するという処理を描こうと下記のブログを参考にして自分で少し書き換えたのですが、うまくいきません。 http://blog.asial.co.jp/12 <参考にした部分> function getFileList($dir) { $files = scandir($dir); $files = array_filter($files, function ($file) { // 注(1) return !in_array($file, array('.', '..')); }); $list = array(); foreach ($files as $file) { $fullpath = rtrim($dir, '/') . '/' . $file; // 注(2) if (is_file($fullpath)) { $list[] = $fullpath; } if (is_dir($fullpath)) { $list = array_merge($list, getFileList($fullpath)); } } return $list; } </参考にした部分> <自分で変更したコード> function getFileList($dir) { $files = scandir($dir); $files = array_filter($files, function ($file) { // 注(1) return !in_array($file, array('.', '..')); }); $list = array(); foreach ($files as $file) { $fullpath = rtrim($dir, '/') . '/' . $file; if (is_dir($fullpath)) { $list[] = $fullpath; $list[] = array_merge($list, getFileList($fullpath)); } } return $list; } </自分で変更したコード> 変更といってもis_fileの部分の削除と$list[] = $fullpath;を追加しただけなのですが、「~ bytes exhausted」というエラーになってしまいます。 再帰関数が内部的にどういう処理をしているのかよくわかってないので、正直変更したコードがどういう動きをしているのかいまいち理解できません。参考書にある再帰関数は腑に落ちないながらも結果としてはそうなるということは理解しました。 あとそれ以前に $files = array_filter($files, function ($file) {   return !in_array($file, array('.', '..')); の部分がわかりません。 scandirの戻り値には要素の最初の方に「.」と「..」が付くのでそれを削除する目的だとブログにはありますが、in_arrayはただ第一引数のものを第二引数から検索するだけのはずなのに、$filesの中身をarray_filtersの処理後に確認してみるとちゃんと「.」と「..」が削除されていて不思議です。あとin_arrayは第一引数のものを第二引数の中から検索するという関数だと思いますが、なぜそれをわざわざ反転させて((array('.', '..'), $file);じゃなく($file, array('.', '..'));)!in_arrayとしてるんでしょうか? *ちなみに引用したブログのコードの動作は確認済みで元のコードは完全に正しいです。引用したコードに文句をつけているわけではなく自分がわかっていないだけです。(^^ゞ 以上です。よろしくお願いします。

共感・応援の気持ちを伝えよう!

  • 回答数2
  • 閲覧数150
  • ありがとう数2

質問者が選んだベストアンサー

  • ベストアンサー
  • 回答No.2
  • shimix
  • ベストアンサー率54% (865/1590)

私もヒントだけ(汗 >in_arrayはただ第一引数のものを第二引数から検索するだけのはずなのに (略) >なぜそれをわざわざ反転させて 第一引数がファイル名の配列ではなくその中からひとつだけ取り出した「ファイル名」だからです(反転しているわけではないです)。で、第二引数に配列(要素は"."と"..")を指定して第一引数のファイル名がどちらかに該当するかどうかをチェックしています。

共感・感謝の気持ちを伝えよう!

質問者からのお礼

ありがとうございます。 なるほどでした。リファレンスにはarray_filterはループしてますと書かないんですかね^^; 良ければ再帰処理の部分もヒントお願いします。

関連するQ&A

  • array_mapの再帰処理がうまく行かない

    長文で失礼します。 array_mapでの再帰処理がうまく行かないのでどこが間違っているか教えてください。 まず、このような配列があります。配列の中に配列があります。 $ary = array(1, 2, null, array("a", null, "c")); この配列の中のnullを"なし"という文字列に変換したいです。 array_mapを使って再帰的にやってみました。 まずはうまく行ったコードから。 ------------------------------------------------------ $ary = array(1, 2, null, array("a", null, "c")); var_dump(null2Nashi($ary)); // nullを"なし"に置換する関数 function null2Nashi(  $in_array ){  if(is_array($in_array)){   return array_map("null2Nashi", $in_array);  } else {   if ($in_array === null){    $in_array = "なし";   }   return $in_array;  } } ------------------------------------------------------ 結果はnullが"なし"に変換されました array (size=4)  0 => int 1  1 => int 2  2 => string 'なし' (length=6)  3 =>   array (size=3)    0 => string 'a' (length=1)    1 => string 'なし' (length=6)    2 => string 'c' (length=1) そしてこの"なし"をコード内で指定するのではなく引数で指定したいと思って無名関数を使って以下のコードにしました。 ------------------------------------------------------ $ary = array(1, 2, null, array("a", null, "c")); var_dump(null2Str($ary, "なし")); // nullを指定文字列に置換する関数 function null2Str(  $in_array, // null値を含む配列  $in_str // null値を変換したい文字列 ){  $n = function($n_array) use($in_str){   if(is_array($n_array)){    return array_map($n, $n_array); //…(1)   } else {    if ($n_array === null){     $n_array = $in_str;    }    return $n_array;   }  };  return $n($in_array); } ------------------------------------------------------ 結果はnullは何も変換されませんでした。 array (size=4)  0 => int 1  1 => int 2  2 => null  3 =>   array (size=3)    0 => string 'a' (length=1)    1 => null    2 => string 'c' (length=1) どうやら(1)のarray_mapが動作していないようです。要素を分解せずに$nの無名関数に渡さずにそのまま第2引数を返しているだけみたいです。 何か対応方法があるでしょうか? どうぞよろしくお願い致します。

    • ベストアンサー
    • PHP
  • 再帰的に処理をする方法

    まとめてサニタイズする方法として下記のように書いてみました。 引数が配列でなければ問題ないのですが、配列だとこんなエラーが出ます。 Warning: array_map() expects parameter 1 to be a valid callback, function 'sanitize' not found or invalid function name in ファイル名 foreachでまわすのも考えましたが、できるならスマートにと思っているのですが どうすれば再帰的な処理ができるでしょうか? $valid = new Valid(); $array = array( 'あああ','いいい','ううう', ); $valid->sanitize( $array ); class Valid{ public function sanitize( $str ){ if ( is_array( $str ) ) return array_map( 'sanitize', $str ); return str_replace( "\0", '', $str ); } }

    • ベストアンサー
    • PHP
  • js初心者 consoleなどについて

    初心者で恐縮ですが、よろしくお願いします。 jqueryを使用してます。 $(function () { obj = function(attr){ $.get('getFileList.php', {attribute : attr.data.value }, function(data){var array = data;}); }; delete obj; $("#file").on('input', {value:'file'}, obj); }); #fileに入力があったらobjが発動し$.getでphpから値を得て出力するという処理を書いています。 うまくいかないので変数arrayにちゃんと値が入っているか確認しようとしconsole.log(array)としたところjsのソースコードがconsoleにそのまま表示され、console.logを消してみてもまったく変化がなくなってしまいました。(console.log(array)したことが原因なのかは不明です。これを描いたあたりから変化がなくなっていたような気がするので。) やってみたこととしてはキャッシュの削除と.onの呼び出しの前にオブジェクトを削除することです。 ですが、やはりその変更点もconsoleに反映されてません。  初歩的かもしれませんがよろしくお願いします。

    • ベストアンサー
    • AJAX

その他の回答 (1)

  • 回答No.1

技術者志望と受け取って、後学のために。 var_dump(変数); こんなんで、変数の中身が出力されます。 この直前に echo '<pre>'; なんて書いておくと出力が見やすくなります。 ループがおかしくて何も出力されないなんて時には、 exit(); なんて書くとそこで処理は中断されます。 と言うことで、 >内部的にどういう処理をしているのかよくわかってない 上記のものをつかえばよくわかりますよ。

共感・感謝の気持ちを伝えよう!

質問者からのお礼

ありがとうございます。

関連するQ&A

  • PHPの再帰関数について

    下記のように関数を作りましたが、思うような結果が出ません。 function saiki($array){ if(count($array) === 1){ return $array; } else { array_pop($array); saiki($array); } } var_dump(saiki(array('いちご', 'みかん', 'りんご', 'すいか'))); /* 欲しい結果 /* array(1) { /* [0]=> /* string(9) "いちご" /* } /* /* /* 実際の結果 /* array(4) { /* [0]=> /* string(9) "いちご" /* [1]=> /* string(9) "みかん" /* [2]=> /* string(9) "りんご" /* [3]=> /* string(9) "すいか" /* } count($array) が 1 じゃなければ array_pop($array) した配列を引数として、再帰的に saiki($array) しているつもりなのですが。。。 array_pop($array) じゃなく unset($array[count($array) - 1]) みたいなことをしても結果は一緒でした。 どうすれば欲しい結果がとれるか(count($array) が 1 以外なら再帰的に繰り返す)、どなたかご教授ください。 よろしくお願いします。

    • ベストアンサー
    • PHP
  • PHP初心者です。

    xamppを使用して勉強してます。 htmlでファイルをアップロードするソースを作り、phpで <meta http-equiv="Content-Type" content="text/html"; charset="UTF-8" /> <?php $file=$_FILES['my_img']; $filePath="./user_img/".$file['name']; move_uploaded_file($file['tmp_name'],$filePath); というコードを書いて実行したところ、 Warning: move_uploaded_file(./user_img/021.jpg): failed to open stream: No such file or directory in  このphpファイルの名前 on line 〇〇行目 Warning: move_uploaded_file(): Unable to move 'C:\xampp\tmp\php6207.tmp' to './user_img/021.jpg' in このphpファイルの名前 on line 〇〇行目 とエラーになってしまいました。 なぜでしょうか?

    • 締切済み
    • PHP
  • 【PHP】関数から渡した引数を正規表現で扱うには?

    下記(1)はディレクトリ「sample_dir」のファイル一覧を取得し、ファイル名「hogehoge」から始まるものだけを一覧表示させたものです。 「hogehoge」以外の文言でも絞り込めるように関数を呼び出して((2))、指定文言を引数で$xに渡したいのですが、引数が認識されません。 引数を正規表現で扱うには、どのように記述したら良いですか。 ご教示をお願いします。 ---------------------------------------- (1) ---------------------------------------- //対象ディレクトリ $dir_s="./sample_dir"; //ディレクトリ内のファイルを取り出す $filelist=scandir($dir_s); //ファイル数をチェック $count=count($filelist); for($i=0; $i<$count; $i++){ $y = ($filelist[$i]); if(preg_match("/^hogehoge/", $y)){ print_r($y); } } ---------------------------------------- (2) ---------------------------------------- function file_search($x){ for($i=0; $i<$count; $i++){ $y = ($filelist[$i]); if($z = preg_match($x, $y)){ print_r($y); } } } file_search("/^filename/"); //引数「filename」でマッチさせたい

    • ベストアンサー
    • PHP
  • PHP初心者です。

    PHP初心者です。 画像を何枚かアップロードし、リサイズをしてImagesフォルダ に収めたのですが、それをPHPとJRUQEYと組み合わせて「次へ」 ボタンをクリックすると、アップロードした順番に画像が スライドするというのを作りたいのですが、スライドする所 でつまづいています。どなたかご教授お願い致します。    ただ、初心者ですのでごく基本的な関数でお願いしたいのと、 質問の内容は実用的ではないと思いますが、どうか宜しく お願い致します。  以下がソースになりますが、手直しもしくは新しいものが あれば宜しくお願い致します。 <html> <meta http-equiv="content-type" content="text/html; charset=euc-jp"> <script src="jquery.js"></script> <script> pic=new Array; c=0; <? $dir=opendir("./images/"); $cnt=0; while( $f=readdir($dir) ){ if(is_file("./images/".$f)){ print("pic[".$cnt."]='".$f."';\n"); $cnt++;} } ?> $(function(){ $("img").attr("src","images/"+pic[c]); }); $cnt=0; $(function btn(){ cnt++; $("img").attr("src","images/"+pic[c]); }); </script> <body> <img /> <form method="post"> <input type="button" value="次へ" onclick="btn()"> </form> </body> </html>    宜しくお願い致します。

    • ベストアンサー
    • PHP
  • PHPのusort関数について

    PHPにおけるusort関数およびuasort uksort関数の使い方がわかりません。 $array = array("b" => "bbbb","c" => "cc","d" => "ddddddddddd","e" => "eee","a" => "a","f" => "ffffffff","g" => "gg","h" => "hh"); 上記のような配列があった場合 uasort($array, function($a,$b){ if (strlen($a) == strlen($b)) { return 0; } if(strlen($a) > strlen($b)){ return -1; }else if(strlen($a) < strlen($b)){ return 1; } } ); print_r($array); 上記のようなコードの場合 ( [d] => ddddddddddd [f] => ffffffff [b] => bbbb [e] => eee [h] => hh [g] => gg [c] => cc [a] => a ) という結果がかえてきます。 ただ、実際このコードでなにがおきてるかわかりません。 まず、uasort関数の第二引数に渡す関数の引数 $a,$bはいったいどんな順番で第一引数の配列からわたされているのでしょうか? そして、$a と$ bの値が同じ場合に0を返した場合なにがおきてるのでしょうか? 同じく return 1;を返すときと return -1;を返すときと いったいどのような処理がおこなわれていてどういうなぜ 上記のような配列を返すことになるのでしょうか? そもそも PHPマニュアルから参照しますが 比較関数は、最初の引数と二番目の引数の比較結果を返します。最初の引数のほうが二番目の引数より大きい場合は正の数を、二番目の引数と等しい場合はゼロを、そして二番目の引数より小さい場合は負の数を返す必要があります。 上記説明も、どうにも理解できません。 どうも全体的にusort関数系の使い方がわかりません。 識者の方よろしくご教授いただけますようお願いします。

    • ベストアンサー
    • PHP
  • phpでファイルの読み込みができません

    phpを使って掲示板のコードを書いたのですが、ファイルの読み込みができないとエラーがでます。 なぜ読み込みが出来ないのでしょうか。サーバにアップした際に、権限の変更などが必要なのでしょうか。 以下が問題のコードの部分になります。 function load_data( $file_name, &$data_array ){ global $sys_mes; if( is_readable ( $file_name ) ){ $data_array = @file( $file_name ); return true; }else{ $sys_mes = "ErrorFile open for load<br> データファイルが開けませんでした<br>\n"; return false; } } このコードを実行するとelse文を実行します。なぜでしょうか

    • 締切済み
    • PHP
  • こんにちは、PHP初心者です。

    こんにちは、PHP初心者です。 Smartyを利用してWebサイトを構築中です。 Smarty.classの派生クラスを作成し、コンストラクタ内でDB接続オブジェクトをprivateプロパティ($_db)に設定しているのですが,query文のところでエラーSELECT * FROM books [nativecode=1046 ** No database selected]となります。ためしにコンストラクタ内でクエリを実行したところテーブルから値を取得できました。なぜコンストラクタ外に出るとエラーになるのかわかりません。どなたかご教示ください。どうぞよろしくお願いします。 下記ソースです。 =====派生クラス======================= <?php $user = "dbuser"; $pass = "dbpassword"; $name = "mobilephp"; $host = "localhost"; require_once("DB.php"); require_once("Smarty/libs/Smarty.class.php"); class MySmarty extends Smarty { private $_db; public function __construct() { $this->Smarty(); $this->template_dir="../templates"; $this->compile_dir="../templates_c"; $this->_db=DB::connect("mysql://$user:$pass@$host/$dbname"); } public function __destruct() { $this->_db->disconnect(); } public function get_db() {return $this->_db;} } ?> ======end===================================== ==========メインのPHP=================================== <?php require_once("../MySmarty.class.php"); $o_smarty=new MySmarty(); $db=$o_smarty->get_db(); $stt=$db->query("SELECT * FROM books");←ここでエラーになる $data=array(); while($row=$stt->fetchRow(DB_FETCHMODE_ASSOC)){ $data[]=array("isbn"=>$row['isbn'],"title"=>$row['title'], "publish"=>$row['publish'],"price"=>$row['price']); } $o_smarty->assign("data",$data); $o_smarty->display("structure.html"); ?>

    • ベストアンサー
    • PHP
  • CSVファイルを更新する処理

    CSVに追加や削除、一覧表示、更新をする処理を書いたのですが 更新処理だけうまくいかずに躓いています。 readメソッドのreturn $files;のところで下記の syntax error, unexpected '$files' (T_VARIABLE)というエラーが出てしまいます。 なぜエラーが出ているか教えていただけるとありがたいです。 <?PHP function con($hantei, $num, $name, $age, $address){ $data = [ $num, $name, $age, $address ]; $datas = [$data]; // 追加 if($hantei === 'add'){ $fp = fopen('data.csv', 'a'); foreach($datas as $data) { $line = implode(',' , $data); fwrite($fp, $line . "\n"); } fclose($fp); //更新 } elseif ($hantei === 'update') { function read() { $FILENAME = 'data.csv'; $file = fopen($FILENAME, 'r'); while($data = fgetcsv($file)) { $files[] = $data; }   fclose($file);   return $files; } function replace($num, $name, $age, $address) { // read() $files = read(); $arr = array(); foreach($files as $key => $el) { // [0][a, b, c, d] // [1][a, b, c, d] if ($el[0] == $num) { // $arr[0][0] = $num ... $arr[$key] = array($num, $name, $age, $address); } else { $arr[$key] = array($el[0], $el[1], $el[2], $el[3]); } }    return $arr; } replace(); function write($arr){   $FILENAME = 'data.csv'; $file = fopen($FILENAME, 'w');   foreach ($arr as $v) {    fputcsv($file,$v); }    fclose($file); } $arr = replace($num, $name, $age, $address); write($arr); //削除 } elseif ($hantei === 'dalete') { $file = file('data.csv'); unset($file[$num]); file_put_contents('data.csv', $file); //一覧表示 } elseif ($hantei === 'list') { $fp = fopen('data.csv', 'r'); $readed = fread($fp, filesize('data.csv')); print_r($readed); fclose($fp); } } con('update', 1, 'name', 3, 'address');

    • 締切済み
    • PHP
  • PHPで2時間前に作成されたファイルを削除する方法

    files/tmpというディレクトリーの中のファイルの作成日が2時間を過ぎたら削除するようにしたいのですが、 <?php function EmptyDir($dir) { $handle=opendir($dir); $currenttime = mktime(); while (($file = readdir($handle))!==false) { $diff = ($currenttime - filemtime($file)); echo '<br/>'; echo 'diff: '.$diff; if($diff != null && $diff >= 7200){ @unlink($dir.'/'.$file); } } closedir($handle); } EmptyDir('files/tmp'); ?> filemtimeの問題だそうです。使い方を間違えているのかな?作成したてのファイルのパス名を引数として渡してecho filemtime("files/" . $_FILES["upfile"]["name"]);のようにすれば正しい値を返すそうですが、以上に書いたEmptyDir関数の中にfilemtime($file)を呼び出せば違う値が返されています。そしてその$diff(現在時間からファイルの作成時間を引いたもの)が微妙にいつも予想された値よりずっと大きいので、作成したてのファイルを含めてディレクトリーの中身が全部消されてしまいます。 どなたか原因のわかる方がいらっしゃいましたら、ご回答を宜しくお願いします。

    • ベストアンサー
    • PHP
  • phpを使いファイル内を検索

    phpでファイル内を検索したいです。 以下のようにphpを書きましたが、やりたいことは1行目から5行目までの中でphpという言葉を検索し6行目から10行目までの中でsnsという文字を検索といったように、行数で分けて検索する言葉も分けたいです。 どのように書いて良いかなどのヒントなどいただけないでしょうか。 $file = dirname(__FILE__) . '/list.txt'; $word = 'php'; if(is_file($file)){ $array = @file( $file, FILE_IGNORE_NEW_LINES); if(in_array($word,$array)){ print_r($word); } } ?>

    • 締切済み
    • PHP