rhuett/csvie

Csvie 是为 Laravel 开发的一个简单的 CSV 文件解析器。Csvie 基于 LeagueCSV,可以快速将数据导入 MySQL 数据库,也可以从数据库导出数据。它还提供了一个方便的抽象类,用于在插入之前快速清理和清洗 CSV 文件。

1.0.3 2021-01-08 23:16 UTC

This package is auto-updated.

Last update: 2024-09-08 09:51:08 UTC


README

Csvie 是为 Laravel 7 开发的一个简单的 CSV 文件解析器。Csvie 基于 LeagueCSV,可以快速将数据导入 MySQL 数据库,也可以从数据库导出数据。它还提供了一个方便的抽象类,用于在插入之前快速清理和清洗 CSV 文件。

工作原理

Csvie 旨在快速将包含数千行数据的 CSV 文件加载到 MySQL 数据库中。这种工作原理背后的思想很简单

  1. 您将 CSV 文件上传到您的服务器。
  2. 使用 Csvie 将文件分块为更小的部分。分块将按数据行进行,而不是按文件全局。
  3. 编写一个自定义 CSV 清洗器以清理分块文件中的数据,然后在服务器上覆盖这些文件。
    1. 请注意,您不必使用包含的 HashCsvCleaner 实现。您可以使用 Rhuett\Csvie\Contracts\CsvieCleaner 接口编写自己的实现。
  4. 直接使用 Load Data 语句 将清理后的文件直接加载到您的 MySQL 数据库中。

安装

通过 Composer

$ composer require rhuett/csvie
$ php artisan vendor:publish --provider="Rhuett\Csvie\CsvieServiceProvider"

请确保将以下行添加到您的 app/config/database.php 文件中

'mysql' => [
    'driver' => 'mysql',
    // ...
    'options' => extension_loaded('pdo_mysql') ? array_filter([
        // ...
        PDO::MYSQL_ATTR_LOCAL_INFILE => true,
    ]) : [],
],

完成这些配置更改后,不要忘记运行

$ php artisan config:cache

请注意,如果您在客户端和服务器端都收到有关此功能未启用的错误,则可能还需要编辑 mysql.cnf

# File Location: /etc/mysql/mysql.conf.d/mysql.cnf
# Add the following to the bottom of the file:
[server]
local_infile=true

...然后运行

$ sudo systemctl restart mysql

用法

单个 CSV 文件导入示例,使用控制器的 store 方法

public function store(Request $request)
{
    $csvie = new Csvie;                 // note: you can pass an array of config overrides if needed
    $modelInstance = new Model;
    $referenceData = 'Whatever I want'; // note: reference data is optional

    // Note: You can pass an array for both column and model UIDs if you need to verify against multiple columns
    $cleaner = new ModelCleaner(
        'ID',           // column name from CSV file to match
        'model_id',     // model ID to verify against column name
        $modelInstance,
        $referenceData  
    );
    
    $fileName = $request->file->store('/', 'uploads'); // move uploaded file from /temp into permanent storage
    $chunkedFiles = $csvie->chunkFiles(
        $csvie->getStorageDiskPath('uploads').$fileName
    );

    foreach($chunkedFiles as $chunk) {
        $chunkData = $csvie->readCsvFile($chunk);
        $cleanData = $cleaner->scrub($chunkData);
        $cleanFile = $csvie->saveCsvFile($chunk, $cleanData);

        $csvie->importCSV($cleanFile, $modelInstance);
    }
    $csvie->clearStorageDisk(); // clear out leftover uploaded file along with its chunks

    return view('view.index')->with([
        'models' => Model::all()
    ]);
}

制作自己的 Csvie 清洗器

只需运行

$ php artisan make:cleaner ModelNameCleaner

...您应该会在 App\Services\CsvCleaners 目录中获得一个类似下面的新文件。请注意,这里显示的额外注释将不会包含在新生成的文件中。

<?php
 
namespace App\Services\CsvCleaners;

use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Rhuett\Csvie\Cleaners\HashCsvCleaner;

/**
 * Class ModelCleaner.
 * 
 * An abstract CsvieCleaner implementation using a custom scrubbing technique based on your needs.
 */
class ModelCleaner extends HashCsvCleaner
{
    /**
     * Custom made function used to clean CSV data.
     *
     * @param  array                           $rowData      - The current row of data pulled from your CSV.
     * @param  ?\Illuminate\Support\Collection $foundModels  - Matched model(s) based on your CSV, otherwise contains null.
     * @param  array                           $newModel     - An empty model indexed with appropriate keys based on your model.
     * @param  \Illuminate\Support\Carbon      $date         - The current date used for timestamps.
     * @param  mixed                           $optionalData - Any custom data that you want to reference in the scrubber.
     * @return array|null
     */
    protected function scrubber(array $rowData, ?Collection $foundModels, array $newModel, Carbon $date, $optionalData)
    {
        // Run checks on $rowData here. Validate, cleanse or completely change!
            // Use parent::updateValue() if you have many possible ways to update a single value within $rowData. Check the function for more information.
            // Return any changes, otherwise return $rowData to make no changes.
            // Return null if you want to remove the data completely.
            // Note: Duplicated headers will be automatically renamed in $rowData.
                // Ex: Header -> Header-1 -> Header-2 ...
            // Note: Since we are not using Eloquent, we will need to manage our timestamps manually.
                // This is why a Carbon datetime instance is passed as a parameter.
    }
}

注意:如果您想更改 CsvCleaner 目录,可以编辑应用配置目录中的 csvie 配置文件。

不要忘记将清理器目录添加到您的 composer.json 文件中(如果需要)

...
"autoload": {
        ...
        "classmap": [
            ...
            "app/Services"
        ]
    },
...

制作自己的 CSV 清洗器

如果您需要一个完全定制的 CSV 清洗器,则可以根据 Rhuett\Csvie\Contracts\CsvieCleaner 合约制作自己的实现

use Illuminate\Support\Collection;
use Rhuett\Csvie\Contracts\CsvieCleaner as CsvieCleanerContract;
use Rhuett\Csvie\Traits\CsvieHelpers;

/**
 * Class MyCsvCleaner.
 * 
 * An abstract CsvieCleaner implementation using a custom scrubbing technique based on your needs.
 */
abstract class MyCsvCleaner implements CsvieCleanerContract
{
    use CsvieHelpers;   // Not needed, review trait to see if it will help you.

    /**
     * Cleans the data within a CSV record to match what's expected by the database.
     * 
     * @param  \Illuminate\Support\Collection $data
     * @return \Illuminate\Support\Collection
     */
    public function scrub(Collection $data): Collection
    {
        // Clean all the data
    }
}

变更日志

请参阅 changelog 了解最近更改的详细信息。

测试

$ composer test

贡献

请参阅 contributing.md 了解详细信息和一个待办事项列表。

安全

如果您发现任何安全相关的问题,请通过电子邮件 im.ryan@protonmail.com 而不是使用问题跟踪器。

鸣谢

许可

MPL-2.0。请参阅 license 文件 了解更多信息。