laravel 排程下載外部 Url 檔案,及更新進資料庫資料

如何下載外部公開 URL

首先利用 Client 套件下載外部 url 的 csv 檔案。

本文撰寫使用抓取此網址https://od.cdc.gov.tw/acute/幼兒常規疫苗接種時間試算表.csv為範例

public function download()
{
$client = new \GuzzleHttp\Client();
$a = $client->get('https:/example/example.csv', ['save_to' => resource_path() . '/download/file.csv']);
return response(200);
}

如何將下載檔案匯進資料庫

使用 laravel-excel 套件將下載的檔案 import 進資料庫

laravel-excel 安裝

因為等等會用到先說說 laravel ORM 的 firstOrCreate 方法

功能 : 將嘗試使用給定的列/值對定位數據庫記錄。如果在數據庫中找不到模型,則會插入一條記錄,其中包含將第一個數組參數與可選的第二個數組參數合併後的屬性

以下為文檔範例:

use App\Models\Flight;

// Retrieve flight by name or create it if it doesn't exist...
$flight = Flight::firstOrCreate([
'name' => 'London to Paris'
]);

// Retrieve flight by name or create it with the name, delayed, and arrival_time attributes...
$flight = Flight::firstOrCreate(
['name' => 'London to Paris'],
['delayed' => 1, 'arrival_time' => '11:30']
);

再來先創建要傳遞的類
檔案可以放在 app/imports/ExampleImport.php

<?php

namespace App\Imports;

use App\Vaccination;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToCollection;

class VaccinationImport implements ToCollection
{
public function collection(Collection $rows)
{
foreach ($rows as $k => $row)
{
if ($k < 1) continue; // 跳過標題

Vaccination::firstOrCreate([ //
'age' => $row[0], 'kind' => $row[1], 'remark' => $row[3]
]);
}
}
}

將 VaccinationImport 對像傳遞給 Excel::import()方法,將告訴包如何導入作為第二個參數傳遞的文件,第二個參數的文件就是上面程式碼下載下來的 csv 檔案放置位置。

該文件應該位於您的默認文件系統磁盤中(參考資料 config/filesystems.php)。

public function import()
{
// 我沒有讓它找默認的,讓他尋找resource資料夾底下檔案
Excel::import(new VaccinationImport, resource_path('/download/file.csv'));
}

功能合併新增排程

在 cmd 輸入以下指令,創建 command 檔案,算是一個可以自己寫命令(shell)的檔案

php artisan make:command DownloadCSV

接著在 DownloadCSV.php 中修改

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use App\Imports\VaccinationImport;
use Maatwebsite\Excel\Facades\Excel;

class DownloadCSV extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'download:vaccination'; // 定義一個命令

/**
* The console command description.
*
* @var string
*/
protected $description = '排程自動下載資料,對比資料庫寫入'; // 一些介紹

/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}

/**
* Execute the console command.
*
* @return int
*/
public function handle() // 主要程式碼
{
$this->download(); // 下載外部csv

$this->import(); // 對比資料庫更新及新增
}

public function download()
{
$client = new \GuzzleHttp\Client();
$client->get('https:/example/example.csv', ['save_to' => resource_path() . '/download/file.csv']);

return response(200);
}

public function import()
{
Excel::import(new VaccinationImport, resource_path('/download/file.csv'));
}
}

修改完成接下來到 app/Console/Kernel.php

修改及導入命令程式碼

<?php

namespace App\Console;

use App\Console\Commands\DownloadCSV; // 導入
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;

class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
DownloadCSV::class
];

/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
// 定義要排程的指令或流程
protected function schedule(Schedule $schedule)
{
// 這邊就會跑command檔案handle函式
// 設定為一個小時跑一次
$schedule->command('download:vaccination')->hourly();
}

/**
* Register the commands for the application.
*
* @return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');

require base_path('routes/console.php');
}
}

程式碼部分就算完成了,接下來就是要設定排程工作

我是在 Linux 上面做開發,如要要讓它排程就要加入 CronJob

在 Linux 上輸入

crontab -e

按 i 編輯,輸入以下這行,它是告訴這個 package 每一分鐘 run 一次php artisan schedule:run 就是跑排程的意思。

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

path-to-your-project改成你的專案路徑

輸入完畢按下 esc,然後輸入:wq 離開並儲存,跑出以下這行表示成功拉

crontab: installing new crontab

參考資料

更多相關排程時間參考這裡

更多排程相關資料請參照laravel Task Scheduling 文檔