--- tags: PHP, Laravel, Backend disqus: HackMD --- # laravel排程下載外部Url檔案,及更新進資料庫資料 ## 如何下載外部公開URL 首先利用Client套件下載外部url的csv檔案。 本文撰寫使用抓取此網址`https://od.cdc.gov.tw/acute/幼兒常規疫苗接種時間試算表.csv`為範例 ```php= 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安裝](https://docs.laravel-excel.com/3.1/getting-started/installation.html) 因為等等會用到先說說laravel ORM的firstOrCreate方法 功能 : 將嘗試使用給定的列/值對定位數據庫記錄。如果在數據庫中找不到模型,則會插入一條記錄,其中包含將第一個數組參數與可選的第二個數組參數合併後的屬性 以下為文檔範例: ```php= 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= <?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)。 ```php= public function import() { // 我沒有讓它找默認的,讓他尋找resource資料夾底下檔案 Excel::import(new VaccinationImport, resource_path('/download/file.csv')); } ``` ## 功能合併新增排程 在cmd輸入以下指令,創建command檔案,算是一個可以自己寫命令(shell)的檔案 ```cmake= php artisan make:command DownloadCSV ``` 接著在DownloadCSV.php中修改 ```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= <?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` ## 參考資料 更多相關排程時間參考[這裡](https://laravel.com/docs/8.x/scheduling#schedule-frequency-options) 更多排程相關資料請參照[laravel Task Scheduling 文檔](https://laravel.com/docs/8.x/scheduling)