webdata
DX推進をサポートする技術者向け情報提供サイト

初心者向けPHP・データベース入門

TOP >初心者向けPHP・データベース入門 >2.11 CSVデータの取り込み(配列と文字コード)

【PHP入門】CSVデータの取り込み(配列と文字コード)

 2023-05-02 (更新日:2023-06-11)

<学習する内容>

 CSVファイルからデータベースへのデータの取り込みを理解します。
 また、変数の配列を使うことにより配列の概念を理解します。

1)CSVファイルのアップロードとデータの取り込み

取り込むCSVファイル(得意先データ)をアップロードします。
その後そのファイルを開いて読込みDBに格納します。

下記のサンプルプログラムをコピーもしくはダウンロードし指定のフォルダーに配置してください。
ファイル名:get_csv.php
配置先:c:\xampp\htdocs\
配置先URL:http://localhost/get_csv.php

サンプルプログラム名:get_csv.php
						<?php

						//DBへの接続
						    include('/xampp/data/conn.php');

						//POSTの受信
							$fnc = filter_input(INPUT_POST, 'fnc');

						//変数リセット
							$mess = null;
							
						//ファイルパスの指定
							$path = '/xampp/htdocs/file/';

						//ファイルのアップロード
						if($fnc == 10){
							$tmpfile = $_FILES['fname']['tmp_name'];
							$filename = $path.$_FILES['fname']['name'];
							if (is_uploaded_file($tmpfile)) {
								if ( move_uploaded_file($tmpfile , $filename )) {
									$mess = $filename . "をアップロードしました。";
									//CSVファイルの読み込み
									$fp = fopen($filename, 'r');
											$i = 1;
									while($data = fgetcsv($fp)){			//1行毎データを取り出す
										$data = mb_convert_encoding($data,'utf-8','sjis');
										if($i > 1){							//1行目は項目のため取り扱わない、項目がない場合はこのifをなくす
											$cnt = count($data);			//列数(要素数)の算出
											for($c = 0 ; $c < $cnt ; $c++){
												$data[$c] = str_replace(array("\r\n", "\r", "\n", "\t"), '', $data[$c]);	//タブキー等の取り除き
											}
											$set_customerCode = $data[0];	//最初の列は得意先コードの場合
											$set_customerName = $data[1];	//2列目が得意先名の場合
											$set_zipcode = $data[2];		//3列目が郵便番号の場合
											$set_address1 = $data[3];		//4列目が住所1の場合
											$set_address2 = $data[4];		//5列目が住所2の場合
											//文字の補正
											$set_customerName = mb_convert_kana($set_customerName,'ASK');	//全角化
											$set_customerName = str_replace(' ','',$set_customerName);		//スペースをとる
											$set_address2 = mysqli_real_escape_string($conn,$set_address2);	//'等をエスケープ
											//データがない場合NULLに変換 ※得意先コードはキーなので無い場合はエラーで止める
											if(empty($set_customerName)){
												$set_customerName = 'null';
											}else{
												$set_customerName = "'$set_customerName'";
											}
											if(empty($set_zipcode)){
												$set_zipcode = 'null';
											}else{
												$set_zipcode = "'$set_zipcode'";
											}
											if(empty($set_address1)){
												$set_address1 = 'null';
											}else{
												$set_address1 = "'$set_address1'";
											}
											if(empty($set_address2)){
												$set_address2 = 'null';
											}else{
												$set_address2 = "'$set_address2'";
											}
											$sql = "insert into Mcustomer
														(
															customerCode
															,customerName
															,zipcode
															,address1
															,address2
														) values (
															$set_customerCode
															,$set_customerName
															,$set_zipcode
															,$set_address1
															,$set_address2
														) on duplicate key update
															customerName = $set_customerName
															,zipcode = $set_zipcode
															,address1 = $set_address1
															,address2 = $set_address2
													;";echo $sql;
											mysqli_query($conn,$sql) or die ("error $sql");
										}
										$i++;
									}	
									fclose($fp);
								} else {
									$mess = "ファイルをアップロードできません。";
								}
							} else {
								$mess = "ファイルが選択されていません。";
							}

						}
					
						echo <<<EOT
						<table bgcolor="#a9a9a9" cellspacing="1">
							<tr bgcolor="white">
							<form method="POST" action="{$_SERVER["PHP_SELF"]}" enctype="multipart/form-data">
									<input type="hidden" value="10" name="fnc">
								<td><input type="file" name="fname">
								<td><input type="submit" value="アップロード">
							</form>
							</tr>
						</table>
						<br>
						{$mess}

						EOT;

						?>
						
<解説>
まず、取り込む得意先のCSVファイルをアップロードします。
13行目
$path = '/xampp/htdocs/file/'; ファイルの配置先の指定
  ※fileというフォルダー作成ください。 必ずしもfileでなくて任意のフォルダー名でもOK。
16行目
if($fnc == 10){ $fncが10なら下記の処理を実施
17行目~20行目
$tmpfile = $_FILES['fname']['tmp_name']; アップロードされた一時ファイルの情報
$filename = .$_FILES['fname']['name']; 配置先とアップロードするファイル名の指定
if (is_uploaded_file($tmpfile)) { 一時ファイルの有無をチェック
if ( move_uploaded_file($tmpfile , $filename )) { 一時ファイルを$filenameに移動
  ifの記載は、move_uploaded_fileが実行されれば下記の処理の実行
92行目~103行目
アップロードのためのブラウザ表示画面
<input type="hidden" value="10" name="fnc"> アップロード実行の指示変数fncが10を指定
<input type="file" name="fname"> 送信物がfileで変数名fnameにファイル名をいれて送信
<input type="submit" value="アップロード"> sumbit処理

次にCSVのデータを取り込みます。
23行目~31行目
$fp = fopen($filename, 'r'); $filenameを'r'読込として開きます。
while(¥ = fgetcsv($fp)){ は開いたcsvファイルをwhile()で1行ずつ取り出し変数$dataに配列形式で 格納します。

配列$dataから列データの取り出しは、左からの列順に$data[0]、$data[1]、$data[2]、$data[3]...
列の最初が]0]、次が[1]というようにです。

この取り出したデータをDBのカラムに合わせinsertします。
$data = mb_convert_encoding($data,'utf-8','sjis'); は文字コードをwin-sjis から utf-8 に変換します。
この変換をしないとSQL文を実行さてら時にエラーを起こしDBに登録されないか、もしくは文字化けされたデータが登録されます。 理由はWindowsで取り扱うデータの文字コードはwin-sjisというものです。一般的にHTMLやDBで取り扱う文字コードはutf-8を使うため 変換してます。本サイトもutf-8として取り扱ってます。
if(59 > 1){ はファイルの1行目は各列の項目が入っているケースが多いので1行目は何も処理しなく1行目以降で 処理を行うために記述してます。項目がなく、データのみのファイル場合if文は必要ありません。
$cnt = count($data); はcsvファイルの列数(要素数)の算出してます。
csvデータの場合、目に見えない、改行キー、タブキーが記載されている時がありうまく取り込みができない場合があります。
下記のプログラムを使って取り除きます。
for($c = 0 ; $c < $cnt ; $c++){ は列データすべて取り出すfor文(繰り返し)です。
  $c = 0は初期値、$c < $cnt0列から最終列、$c++は繰り返し毎に1を加算
$data[$c] = str_replace(array("\r\n", "\r", "\n", "\t"), '', $data[$c]); タブキー等の取り除く関数 } CSVファイルのデータの中にカンマ「,」があると読み込みの際、データの区切りとなるので事前の削除が必要です。特にカンマ区切りの数字に気を付けてください。

2)配列について

一つの変数の中に複数のデータを代入されたものを配列といいます。上記の場合でも$dataの中に$data[0]、$data[1]が代入 されてます。fgetcsv($fp)の関数では、カンマ区切りのデータ順に配列として代入します。
例)csvのデータは 10001,ABC株式会社,東京,東京,芝ビル10階
このデータが
$data[0] が10001
$data[1] がABC株式会社
$data[2] が東京
$data[3] が東京
$data[4] が芝ビル10階
となってます。
[0]、[1]の数字の部分を文字しているのがSQLの$row = mysqli_fetch_array()です。
$sql = "select customerCode,customerName,zipcode,address1,address2 from Mcustomer where customerCode = 10001;";
$res = mysqli_query($conn,$sql) or die("エラー $sql");
$row = mysqli_fetch_array($res);
  $customerCode = $row["customerCode"];
  $customerName = $row["customerName"];
  $zipcode = $row["zipcode"];
  $address1 = $row["address1"];
  $address2 = $row["address2"];
mysqli_fetch_array()により$rowの中にカラムに合わせたキー["customerName"]をつけて格納してくれてます。
このような配列を連想配列といいます。
echo文で$rowを表示させるArrayしか表示されません。表示させるには
print_r($row)、var_dump($row) で表示できます。

下記のサンプルプログラムをコピーもしくはダウンロードし指定のフォルダーに配置してください。
ファイル名:array.php
配置先:c:\xampp\htdocs\
配置先URL:http://localhost/array.php

サンプルプログラム名:array.php
						<?php
						//DBへの接続
							include('/xampp/data/conn.php');
						
						$sql = "select customerCode,customerName,zipcode,address1,address2 from Mcustomer where customerCode = 10001;";
						$res = mysqli_query($conn,$sql) or die("エラー $sql");
						$row = mysqli_fetch_array($res);
						
						echo 'print_rの場合<br>';
						print_r($row);
						
						echo "<br><br>";
						
						echo 'var_dumpの場合<br>';
						var_dump($row);
						
						?>
						
print_rの場合(見やすくするため改行してます)
Array ( [0] => 10001 [customerCode] => 10001
  [1] => ABC株式会社 [customerName] => ABC株式会社
  [2] => 220-0001 [zipcode] => 220-0001
  [3] => 東京都港区芝1-1 [address1] => 東京都港区芝1-1
  [4] => 芝ビル10階 [address2] => 芝ビル10階
)

var_dumpの場合(見やすくするため改行してます)
array(10) {
  [0]=> string(5) "10001" ["customerCode"]=> string(5) "10001"
  [1]=> string(21) "ABC株式会社" ["customerName"]=> string(21) "ABC株式会社"
  [2]=> string(8) "220-0001" ["zipcode"]=> string(8) "220-0001"
  [3]=> string(27) "東京都港区芝1-1" ["address1"]=> string(27) "東京都港区芝1-1"
  [4]=> string(14) "芝ビル10階" ["address2"]=> string(14) "芝ビル10階"
}

関数で配列データを作ってましたがプログラムでも書けます。
例1)
 $data = [
       '10001'
       ,'ABC株式会社'
       ,'220-0001'
       ,'東京都港区芝1-1'
       ,'芝ビル10階'
      ];
例2)
 $data[0] = '10001';
 $data[1] = 'ABC株式会社';
 $data[2] = '220-0001';
 $data[3] = '東京都港区芝1-1';
 $data[4] = '芝ビル10階';
例3)連想配列
 $data = [
       'customerCode'=>'10001'
       ,'customerName'=>'ABC株式会社'
       ,'zipcode'=>'220-0001'
       ,'address1'=>'東京都港区芝1-1'
       ,'address2'=>'芝ビル10階'
      ];

上記サンプルプログラムで実際に表示を確認したり、配列データを登録したり、またgoogleで「php 配列」と検索し 調べたりして理解を深めてください。

3)文字コードについて

文字コードとはコンピュータで文字を取り扱う(表示したり格納したりと)ために定めたものです。
例えば、「表」という感じは、SJISに場合で「955C」、utf-8では「E8 A1 A8」となります。
Wundowsはwin-sjisでWeb系はutf-8が一般的です。HTML文ではどの文字コードで書かれているか
タグにで記載しています。この記載がないと文字化けを起こしちょんと表示されません。 また、DBでもどの文字コードを使うかの設定します。尚Xamppはデフォルトでutf-8となってます。


得意先マスターを使った日報システム作成に進みます。
まずは部署、担当者マスターの作成です。