ローカルのCSVをMysqlへアップロードする
それは簡単にみえるMysqlの処理が用意されている「 LOAD DATA LOCAL INFILE $file INTO TABLE tb1 FIELDS TERMINATED BY ','」などとPHPを使うと、エンコードの問題や、サーバの.iniの問題などでなかなかシンプルにいかず、何より原因の解明が非常にややこしい。
問題は、文字化け一つとってもPHPなのかMysqlなのか、はたまたCSVなのかわかりにい。
テキストで同じものを用意したりしてかなり手こずった。あとは解決して納品したとして、クライアントが使うCSVの形式を指定していたのでは担当者が変わったり、6ヶ月ごとの商品の入れ替えの度に問い合わしの電話が鳴り、その度に仕様書を見るのはこちらなので、不安要素は最大限取り除く目的がある。
設計
●ローカルからCSVデータをPHPを使って引き込む
//フォームから送られたデータは、$_FILES["csvfile"]["tmp_name"]で受け取ることができる。
$tmp = fopen($_FILES['csvfile']['tmp_name'], "r");
fopen()関数で、ファイルを開く。"r"というのは「読み込み専用」という指示です。
//ここで2次元配列にする。fgetcsv()関数により、csvデータを読み込む。
mb_convert_variables("UTF-8", "SJIS-win", $csv);
//文字化け防止のため、UTF-8に変換する// 配列 $csv の文字コードをSJIS-winからUTF-8に変換
$lim = count($csv);
//for文で読み込むために、配列の最大行数を出す
ここまででローカルから対象のCSVを引き込み、ファイルを開き文字化け防止のエンコード処理を施し、for,foreach,whileなどで回すための最大値を計算しています。
●今回はforでCSVから取り出した連想配列をとりだす。ポイントはimplodeでMysqlに挿入すする形式に変換している
//iに0を代入、$limに入れてある行数の最大数までループさせている、i++で1回のループごとにiの値が増えていく。
for($i=0; $i<=$lim; $i++){
//最後のループは多いので減らす
if($lim > ($i+1)){
$ar = $csv[$i];
$aaa = implode("\",\"", $ar);
//echo $aaa,"\n";//確認用書き出し
}
これでCSVの各行がカンマで区切られ、Mysql文に代入する用意が完了。
●Mysqlを接続し、単純にSQLをmysql_queryでDBへとインポートさせる。
//必要Mysql情報
$host = "localhost";
$mysql_user = "user";
$mysql_password = "pass";
$db = "db";
$tb = "tb1";
//接続
$cn = mysql_connect($host,$mysql_user,$mysql_password);
if(!$cn){
die("db connect Error");
}
if(!(mysql_select_db("$db"))){
die("db select error");
}
//今回はとにかくシンプルに設定を少なくするため、INSERTで挿入することにします。
$sql = "INSERT INTO $tb VALUES(\"$aaa\");";
//echo $sql;//確認用書き出し
$query = mysql_query($sql);
mysql_close($cn);//Mysqlの接続を閉じる
}
}//ifを閉じる
全文はこちら
データ選択用のhtmlフォーム<form method="post" action="ファイル名.php" enctype="multipart/form-data">
<input type="file" name="csvfile" /><br />
<input type="submit" name="csvsub" value="csv呼出" /><br />
</form>
<?php
//フォームから送られたデータは、$_FILES["csvfile"]["tmp_name"]で受け取ることができる。
$tmp = fopen($_FILES['csvfile']['tmp_name'], "r");
while ($csv[] = fgetcsv($tmp, "1024")) {}
//fopen()関数で、ファイルを開く。"r"というのは「読み込み専用」という指示です。
//ここで2次元配列にする。fgetcsv()関数により、csvデータを読み込む。
mb_convert_variables("UTF-8", "SJIS-win", $csv);
//文字化け防止のため、UTF-8に変換する// 配列 $csv の文字コードをSJIS-winからUTF-8に変換
$lim = count($csv);//for文で読み込むために、配列の最大行数を出す
for($i=0; $i<=$lim; $i++){
if($i < ($lim-1)){
$ar = $csv[$i];
$aaa = implode("\",\"", $ar);
//echo $aaa,"\n";
$host = "サーバホスト";
$mysql_user = "ユーザ名";
$mysql_password = "パスワード";
$db = "データベース名";
$tb = "テーブル名";
$cn = mysql_connect($host,$mysql_user,$mysql_password);
if(!$cn){
die("db connect Error");
}
if(!(mysql_select_db("$db"))){
die("db select error");
}
$sql = "INSERT INTO tb1 VALUES(\"$aaa\");";
echo $sql;
$query = mysql_query($sql);
mysql_close($cn);
}
}
?>
追記(201409)
mysql関数が非推奨になったため、MySQLにはPDOなどで接続を強くお勧めします。
(ほとんどのレンタルサーバではPHP5.3以上となっている為、接続エラーが返されます)
【修正方法】
全体の流れはほとんど一緒、接続方法を変更するだけでも利用できます。
(修正前)
(修正後)
query("SELECT 'Hello, World.' AS msg FROM DUAL"); $row = $rec->fetch_array(MYSQLI_ASSOC); echo htmlentities($row["msg"]); $rec->free(); $con->close(); ?>
0 件のコメント:
コメントを投稿