【PHP】フォルダ内のファイルソースを配列で一括取得する

フォルダ内のソースコードを複数個修正する作業のために自動で一括でやってくれるプログラムがほしい!

ということで今回は、そのプログラムの二部目「フォルダ内のファイルソース配列でを一括取得する」ソースをここに残しておく。

ファイルの内容を返す関数

ファイルを扱う際に強力な関数として file_get_contents()関数がある。

パスを引数に渡すと、ファイルの内容(ソースコード)を読み込んで返してくれる。

今回は /Test/test1.php を用意。

$path = './Test/test1.php';
$source = file_get_contents($path);

var_dump($source);

ブラウザで確認する。

string(33) "<?php
echo "Hello, World!!";
 ?>
"

ブラウザには直接表示されていなかったけれどソースコードを表示したらみることができた。

というわけでこの file_get_contents()関数を使ってフォルダの中のすべてのファイルを配列として取り出すファンクションを作成してみる。

関数を作成する

function readPath($paths=[])
{
	$file_contents = [];

	foreach ($paths as $path) {
	// file_get_contents関数でファイルデータを読み込む
      $file_content = file_get_contents($path);
      array_push($file_contents, $file_content);
	}

	return $file_contents;
}

基本的な機能としてはこんな構成になる。
pathの配列を渡してそれぞれのパスについてfile_get_contents()を適用している。

フォルダの中のファイルのパスを配列として受け取る方法は前回の記事でまとめているので気になる方はそちらをご覧ください。

それをforeachで回して array_push() すると返り値としてすべてのデータが入った配列を受け取れる。

パスをキー値につけたい

これで実行してみると

$paths =[
  'Test/test1.php',
  'Test/test_dir1/test2.php',
  'Test/test_dir1/test3.php',
  'Test/test_dir2/test4.php',
  'Test/test_dir2/test_dir2-2/test5.php'
];

$contents = readPath($paths);
var_dump($contents);


function readPath($paths=[])
{
	$file_contents = [];

	foreach ($paths as $path) {
			// file_get_contents関数でファイルデータを読み込む
      $file_content = file_get_contents($path);
      array_push($file_contents, $file_content);
	}

	return $file_contents;
}

結果(ファイルの中身はすべてさっきと同じ)

array(5) { [0]=> string(33) " " [1]=> string(33) " " [2]=> string(33) " " [3]=> string(33) " " [4]=> string(33) " " }

無事すべて取得することができた。

ただし、これではどのファイルが何番目にあるのかがわからないのでキー値にパスを付けて連想配列にしてみる。

function readPath($paths=[])
{
	$file_contents = [];

	foreach ($paths as $path) {
		// file_get_contents関数でファイルデータを読み込む
    $file_content = file_get_contents($path);
    array_push($file_contents, $file_content);
	}
  $file_contents = array_combine($paths, $file_contents);
	return $file_contents;
}

結果

array(5) {
[“Test/test1.php"]=> string(33) " "
[“Test/test_dir1/test2.php"]=> string(33) " "
[“Test/test_dir1/test3.php"]=> string(33) " "
[“Test/test_dir2/test4.php"]=> string(33) " "
[“Test/test_dir2/test_dir2-2/test5.php"]=> string(33) " “
}

array_combine()関数の1文を付け加えるだけで簡単にキー値にパス情報がつけられた。

ただし、この関数は$pathsと$file_contentsの数が一致していないといけない。
しかもファイルの読み込み権限がひとつだけ無い場合や、うっかりパス情報を間違えてしまったりファイルが消えていたりしたときにうまく働かなくなる。

ERRORに対応させる

というわけで

  • ファイルが見つからなかったとき
  • ファイルの読み取り権限がなかったとき

それぞれに対して配列がバグらないようにうまい具合に形づける。

function readPath($paths=[])
{
	$file_contents = [];

	foreach ($paths as $path) {
		//ファイルが存在するか
		if (!file_exists($path)) {
			array_push($file_contents, 'ファイルが存在しません。');
		}
		// ファイルを読み取れるか確認
		elseif (!is_readable($path)) {
			array_push($file_contents, 'ファイルの読み込み権限がありません。');
		} else {
			// file_get_contents関数でファイルデータを読み込む
      $file_content = file_get_contents($path);
      array_push($file_contents, $file_content);
		}
	}
  $file_contents = array_combine($paths, $file_contents);
	return $file_contents;
}

こうすることでファイルの内容自体がエラーメッセージとして配列に格納されるのでキーと値が寸分狂わず対応づけられる。

試しに test1.php をなくして、test2.php の読み込み権限を奪う。

array(5) {
[“Test/test1.php"]=> string(36) “ファイルが存在しません。"
[“Test/test_dir1/test2.php"]=> string(54) “ファイルの読み込み権限がありません。"
[“Test/test_dir1/test3.php"]=> string(33) " "
[“Test/test_dir2/test4.php"]=> string(33) " "
[“Test/test_dir2/test_dir2-2/test5.php"]=> string(33) " “
}

狙いどおりtest1.phpとtest2.phpの値にエラーメッセージが代入できた。

メッセージを渡す関数

これで var_dump() ないし print_r() などで確認すると確かめられるが、いちいちファイルの中身がすべて展開されてその中からエラーメッセージを探すことになるのでまだ実用的ではない。

エラーが起こったときだけメッセージを返してくれる関数を作成した。

function readPathChecker($file_contents)
{
	$i = 0;
  foreach ($file_contents as $path => $file_content) {
    switch ($file_content) {
      case 'ファイルが存在しません。':
        echo $i. $path. ' : '. $file_content. '<br>';
        break;
      case 'ファイルの読み込み権限がありません。':
        echo $i. $path. ' : '. $file_content. '<br>';
        break;
      default:
      echo $i. ' OK'. '<br>';
    }
		$i++;
  }
}

こうすることで

0Test/test1.php : ファイルが存在しません。
1Test/test_dir1/test2.php : ファイルの読み込み権限がありません。
2 OK
3 OK
4 OK

何番目のどこのファイルがエラーなのかがひと目でわかるようになった。
もちろん「OK」はわざわざ表示させなくてもいいし気分的にはあれば気持ちいてところ。

イキってswitch文を使う必要もなかったけれど、エラーそれぞれに対応させたり、表示させるメッセージの内容をそれぞれ変えたりと応用できると思った。

まとめ

前回のパスを取得する関数と組み合わせることでフォルダ内のすべてのファイルの内容を配列として取得できるようになった。

ちょっと条件式を組み込めばほしいファイルコンテンツだけを格納することも可能になってくる。

次はいよいよファイル内の修正部分をすべて一括で書き換えるファンクションに挑戦だ!