Laravel

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

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

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 文檔

comments powered by Disqus