PHP에서 CSV 파일을 읽고 배열

기반계의 개발 등을 하고 있으면, 매출 데이터나 고객 데이터등이 쓰여진 Excel 파일이나, CSV 파일을 읽어들여, DB에 격납한다고 하는 장면이 보치보치 있기 때문에, 대응하기 쉽도록 Qiita에 정리해 둘다.

환경



PHP 7.1.7
Laravel 5.6.33 (pure에서도 문제 없다, 사용하는 것은 pure 표준의 함수인가 개발한 환경이 우연히 Laravel이었을 뿐)
MySQL 5.7.22

사용하는 주요 함수



fopen()



첫 번째 인수로 지정된 파일을 두 번째 인수로 지정된 파일 모드로 엽니 다.
이 경우 CSV 파일을 여는 데 사용됩니다.
파일 모드에 관해서는 문서를 참조하는 것이 가장 좋다고 생각한다. 우선 이번 사용하는 것은, 읽기 전용으로 파일이 없었던 경우 false를 돌려주는, 'r'이 된다.

ex.)
fopen('指定したファイル', 'ファイルモード');

fgetcsv()



인수에 지정한 fopen() 함수를 통과한 후의 CSV 파일을 행마다 배열화 한다.
fopen () 함수를 통과 한 후에는 사용할 수 없으므로주의

ex.)
fgetcsv(引数);

fclose()



인수에 지정된 파일을 닫습니다.
이번에는 CSV 파일을 닫는 데 사용됩니다.

ex.)
fclose(引数);

절차



흐름으로는
①fopen() 함수로 CSV 파일을 엽니다.
②CSV 파일을 fgetcsv() 함수로 행별로 추출(행별 추출이므로 횟수 돌려주지 않으면 추출할 수 없다)
③fclose() 함수로 CSV 파일을 닫는다.
된다.

View측Form의 내용에 관해서는 자세한 이야기는 생략하지만,

ex.)
{!! Form::open(['route' => 'hoge.hoge', 'files' => true]) !!}
    {{Form::file('csvfile')}}
    {{Form::submit('送信')}}
{!! Form::close() !!}


이런 느낌이겠지요. type 속성은 'csvfile'로 하고 있다.
또한 Form::open () 메서드의 'files'키를 'true'로 설정하지 않으면 파일 업로드를 지원하지 않으므로 잊지 마세요.
우선은 CSV 파일을 열어준다.

ex.)

public function hoge(Request $request)
{
    $input = $request->all(); 
    $csvfile = $input['csvfile']; 
    $importfile = fopen($csvfile, "r"); 
}

fopen() 함수의 제1 인수에는 form로부터 보내져 온 CSV 파일이 대입되고 있는 '$csvfile'가, 제2 인수에는 읽기 전용의 파일 모드가 기술되고 있다.
덧붙여서 이번은 Form 경유의 CSV 파일을 사용하고 있는 것이지만, fopen() 함수의 제1 인수에 직접 Path를 기술해 지정할 수도 있으므로, 만약 거동 체크등을 하고 싶은 경우 등에 사용하면 좋다 합시다.

이어서 fgetcsv () 함수를 사용하여 CSV 파일의 각 행을 검색합니다.

ex.)
while($line = fgetcsv($importfile)) {
    //headerのスキップ処理
    if($line[0] == 'id') {
      continue;
    }
    $importline = [
                      'hoge' => $line[1],
                      'fuga' => $line[2]                               
                  ];
    $array[] = $importline;
}

이번은 while문으로 처리해 보았다.
주의점은 CSV 파일이라고 대략 「헤더」(id, 이름, 연령, 성별적인 녀석)가 기술되고 있다고 생각하지만, 그것도 읽어 버리므로 조건식으로 스킵 시킬 필요가 있다. (위에서는 fgetcsv에서 $line에 행의 내용을 배열로 취득했을 때 $line[0]이 id라는 문자열이었을 경우 처리를 건너뛰고 있지만 여기는 자신이 쿨하다고 생각하는 방법으로 날려 줘서 좋다고 생각한다..)
그리고는 $line의 내용을 연상 배열화해, 그 연상 배열을 한층 더 배열에 넣어 다차원 배열화해 준다. 이 처리는 $ line이 false를 반환 할 때까지 반복됩니다.

이어서 DB에 저장한다.

ex.)
    while() {
    ...
    }
    DB::insert($array);
    fclose($importfile);
}

DB에 격납하는 방법은 몇개인가 있다고 생각하지만, 이번 주의인 것은 save() 메소드를 사용하면 마지막 꼬리의 행 밖에 반영되지 않기 때문에, insert 메소드로 처리하면 모든 행을 DB에 보존할 수 있다. (DB 부분은 DB 파사드로 바꾸고, DB 파사드는 use해 둘 필요가 있으므로 잊지 말고)
마지막으로 fclose() 함수로 CSV 파일을 닫아준다.
그런 다음 톱 페이지로 리디렉션하면 처리로 종료됩니다.
비교적 급한 것이지만 정리로서는 이런 느낌입니까.

요약 코드



모두 정리하면 이런 느낌

ex.)
public function hoge(Request $request)
{
    $input = $request->all(); 
    $csvfile = $input['csvfile']; 
    $importfile = fopen($csvfile, "r"); 

    while($line = fgetcsv($importfile)) {
        //headerのスキップ処理
        if($line[0] == 'id') {
          continue;
        }
        $importline = [
                        'hoge' => $line[1],
                        'fuga' => $line[2]                               
                      ];
        $array[] = $importline;
    }
    DB::insert($array);
    fclose($importfile);
    return redirect()->to('遷移したいページ');
}

좋은 웹페이지 즐겨찾기