Laravelで銀行マスタ更新のバッチ処理

## 目的
銀行マスタのZipファイルを下記のURLよりダウンロードして、Laravelのバッチで銀行マスタを定期的に更新する処理を実装する
http://ykaku.com/ginkokensaku/ginkositen1.zip

## コマンドのクラス定義を追加
app/Console/Kernel.php

```
    protected $commands = [
        DownLoadBankMasterZipFile::class,
    ];
    
    protected function schedule(Schedule $schedule)
    {
        $schedule->command('downLoadBankMaster')->dailyAt('02:00');
    }
```
## バッチクラスを作成
下記のコマンド実行でバッチクラスを作る
php artisan make:console DownLoadBankMasterZipFile --command="downLoadBankMaster"

## バッチクラスの中身
app/Console/Commands/DownLoadBankMasterZipFile.php

```
class DownLoadBankMasterZipFile extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'downLoadBankMaster';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '銀行マスタZIPファイルダウンロード';

    /**
     * Create a new command instance.
     *
     */
    public function __construct()
    {
        parent::__construct();
    }
    
    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        //
    }
}

```
## handleメソッドにメインの処理を書く
```
    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        echo '▲▲▲▲▲▲▲処理開始▲▲▲▲▲▲'.PHP_EOL;

        // ファイル名「bank_master.zip」でディレクトリ「bank/」に保存する場合
        $saveFileName = 'bank_master';
        $this->file_download('http://ykaku.com/ginkokensaku/ginkositen1.zip', 'bank', $saveFileName);

        //zipファイルを解凍せずにファイルの内容を読み取る
        $zip = new \ZipArchive();
        if (!$zip->open('bank/'.$saveFileName. '.zip')) {
            echo '▲▲▲zipファイルのオープンに失敗しました。▲▲▲'.PHP_EOL;
            exit(1);
        }

        // ginkositen1.txtというファイル名が取得できる
        $filename = $zip->getNameIndex(0);
        // ファイルポインタを取得
        $fp = $zip->getStream($filename);

        $i=0;
        while (!feof($fp)) {
            $i++;
            $line = fgets($fp);
            echo $line;
            //読取&DB更新処理書けばOK
        }
        fclose($fp);
        $zip->close();
        echo '▲▲▲▲▲▲▲処理終了▲▲▲▲▲▲'.PHP_EOL;
    }
}
```
## PHPでURLからローカルにファイルをダウンロード
```
    /**
     * PHPでURLからローカルにファイルをダウンロードする
     *
     * @param  $url
     * @param  $dir
     * @param  $save_base_name
     * @return
     */
    private function file_download($url, $dir='.', $save_base_name='' ){
        if ( ! is_dir($dir) ){ die("ディレクトリ({$dir})が存在しません。");}
        $dir = preg_replace("{/$}","",$dir);
        $p = pathinfo($url);
        $local_filename = '';
        if ( $save_base_name ){ $local_filename = "{$dir}/{$save_base_name}.{$p['extension']}"; }
        else{ $local_filename = "{$dir}/{$p['filename']}.{$p['extension']}"; }
        if ( is_file( $local_filename ) ){ print "すでにファイル({$local_filename})が存在します<br>\n";}
        $tmp = file_get_contents($url);
        if (! $tmp){ die("URL({$url})からダウンロードできませんでした。");}
        $fp = fopen($local_filename, 'w');
        fwrite($fp, $tmp);
        fclose($fp);
    }

```

### 実行時発生したエラー&解決法
```
//zipファイルを解凍せずにファイルの内容を読み取る
$zip = new ZipArchive();
```
下記のエラーが発生
<img width="1108" alt="スクリーンショット 2019-11-13 14.33.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274686/9993b4e2-463a-af74-b0e0-9b34062025c1.png">

実際には App\Http\Controllers\ZipArchive というクラス名であると解釈されるらしく、
次のようにクラス名の先頭に \ をつけて解決

```
$zip = new \ZipArchive();
```

## cron登録してみる
crontabを書いておけば、app/Console/Kernel.phpのscheduleメソッドに書かれたバッチを指定された時間に動作させる

```
* * * * * php /path/to/project/artisan schedule:run 1>> /dev/null 2>&1
```


## 参照リンク
https://pgmemo.tokyo/data/archives/825.html
https://symfoware.blog.fc2.com/blog-entry-1891.html
https://qiita.com/yamikoo@github/items/c0250e8f0548534adbd2
https://teratail.com/questions/32085
https://qiita.com/ritukiii/items/a70d89fa988b2d9afbc4