人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

PHPで次の物を作成してください。
私の環境で動く物を最初に完成された方に300ポイント、他二人まで50ポイント差し上げます。

下記のようにデータが一行記入された復数のCSVファイルが特定のフォルダ内にあります。
1116.csv
愛知県,山田太郎,Yamada Taro,無,教師

4564.csv
愛知県,田中一郎,Tanaka Ichirou,有,プログラマー

hoge.php 内のフォームで検索して、マッチしたキーワードを含むCSVファイルがあった場合、名前、職業、ファイル名を表示するというプログラムを作成してください。つまり「愛知県」が検索された場合次のように表示されます。
フォーム
田中一郎 プログラマー 4564.csv
山田太郎 教師 1116.csv

ただし下記の点にご留意ください。
・コメントは多めに振ってください。
・CSVファイルがあるフォルダのパスはお任せします。
・表示結果はCSV内に「有」と書れている物が上に、次にローマ字名の順でソート。
・hoge.phpの文字コードはUTF-8なので、文字化け対策もお願いします。
・復数のキーワード検索は半角か全角のスペースで区切ったand検索。
・セキュリティもご配慮ください。

環境はXP、Xampp、PHP5です。
よろしくお願いします。


●質問者: taroemon
●カテゴリ:コンピュータ ウェブ制作
✍キーワード:CSV hoge PHP UTF-8 XAMPP
○ 状態 :終了
└ 回答数 : 1/1件

▽最新の回答へ

1 ● うぃんど
●300ポイント ベストアンサー

毎回毎回ファイル検索させるのは非常に効率が悪い事だと知っておられると思いますし、そのため、このような処理は通常行うことがなく、今回用にゼロから作ってみました

作った際のチェックポイントも一部コメントの形で残してありますので活用してもらえればうれしいですね

Windows版のxamppは使っておらず Linux版で独自にビルドしたものを組み合わせて使ってますので、万全とは言えませんし、

phpでは同じことを実現できる関数が幾重にも存在する場合があり、バージョンによって細かに違う場合もありますので、下記が万能というわけではありません

詳細はコード中のコメントを読んでください

<?php
 // 実際に設置する際にはapacheの仮想ディレクトリ外にcsvファイルを置かなければならないが、ここではスクリプトと同一ディレクトリとする
 $dir = '.';
 //
 // パラメータkeywordsが存在しなければスルー
 if ( isset( $_POST["keywords"] ) ) {
 $keywords = preg_split( '/(\s| )+/', strip_tags( $_POST["keywords"] ) ); // タグを取り除いた後、キーワードを分割
 // パラメータkeywordsが空ならばスルー
 // echoで文句を言ってもいいけどね(笑)面倒だから無視してスルー
 if ( !empty( $keywords[0] ) ) {
 $pt = '/(?=.*' . join( ')(?=.*' , $keywords ) . ')/i'; // AND検索用パターン作成
 // 与えられたキーワードと作成したパターンの表示
 print_r($keywords);
 echo '<br />' . $pt . '<hr />';
 /*
 // AND検索のテスト 仮のデータ$aと比較して適合すれば OK を表示
 echo $a = ' あかさたな はまやらわ かきくけこ さしすせそ';
 if ( preg_match( $pt, $a ) ) echo ' OK';
 echo "\n";
 echo $a = ' あかさたな はまやらわ かきくけこ えあいうえおさしすせそ';
 if ( preg_match( $pt, $a ) ) echo ' OK';
 */
 // 該当した情報を格納する配列を準備(後から有無を混在させたソートをするのは面倒なので有無で最初から分けることにした)
 $list1 = array(); 
 $list2 = array();
 $errorList = array(); // 内容に不備があるcsvのリスト、チェック不要なら要らない
 $dh = opendir( $dir ) or die( "error" ); // dirを開く
 while ( ( $file = readdir( $dh ) ) !== false ) {
 // ファイル名で絞込み
 if ( preg_match( '/\d{4}.csv$/', $file ) ) {
 // 便利なfgetcsv関数も存在するけれど文字化け対策としてfile_get_contentsで読み込んでから分割する手順とした
 // Windows上のcsvファイルなので文字コードを判断する優先順位の1番目にsjis-winを明示
 $readFile = mb_convert_encoding( file_get_contents( $file ), "UTF-8", "sjis-win, SJIS, UTF-8" );
 if ( preg_match( $pt, $readFile ) ) {
 /*
 // 対象ファイルの中身を文字化けしたりせずに正しく読み込んでいるかどうかのテスト出力
 echo $readFile . "<br />";
 */
 $csv = split( ',', $readFile ); // 1行目をカンマで分割
 // csvの中身を項目数で簡易的にチェック。チェック不要ならキーとしてリストに追加だけすればいい
 if ( count( $csv ) == 5 ) {
 // 同姓同名の存在も考えて、ローマ字表記+ファイル名をキーとしてリストに追加
 if ( $csv[3] == '' ) {
 $list1[($csv[2] . $file)] = join( ',', array( $csv[1], $csv[4], $file ) );
 } else {
 $list2[($csv[2] . $file)] = join( ',', array( $csv[1], $csv[4], $file ) );
 }
 } else {
 $errorList[] = $file;
 }
 }
 }
 }
 closedir($dh);
 // キーでソート
 ksort( $list1 );
 ksort( $list2 );
 // キーでソートしたものを簡易出力
 // 変数に格納された値の出力方法や、テーブルでの出力方法は、前回ご質問のものを参照して改良してください
 // http://q.hatena.ne.jp/1278940933
 // トラブル時に原因をつかみにくくなるので、何度もテストして、処理の内容もよく把握できるようになるまでは簡易出力のままがよいです
 echo '<hr /><pre>';
 print_r( $list1 );
 print_r( $list2 );
 echo '</pre><hr />';
 }
 }
?>
 <form action="<?= $_SERVER['SCRIPT_NAME'] ?>" method="POST">
 <input type="text" name="keywords" size="50"><br>
 <input type="submit" value="送信" />
 </form>
◎質問者からの返答

私の環境で動きました。

丁寧なコメントありがとうございました。分かりやすかったです。

$list1の配列の使い方は僕にとって斬新で参考になりました。

str_getcsvはまだ新しい関数なので、explodeを使うことにします。

ありがとうございました。

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ