glhd / conveyor-belt
2.1.0
2024-03-12 20:00 UTC
Requires
- php: >= 8.0
- ext-json: *
- guzzlehttp/guzzle: ^7.0
- halaxa/json-machine: ^1.0
- illuminate/collections: ^8|^9|^10|^11|12.x-dev|dev-master
- illuminate/console: ^8|^9|^10|^11|12.x-dev|dev-master
- illuminate/http: ^8|^9|^10|^11|12.x-dev|dev-master
- illuminate/support: ^8|^9|^10|^11|12.x-dev|dev-master
- jdorn/sql-formatter: ^1.2
- openspout/openspout: ^4.0
- symfony/console: ^5.4|^6.0|^7.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- glhd/laravel-dumper: ^1.0
- mockery/mockery: ^1.3
- orchestra/testbench: ^6.24|^7.10|^8|^9|9.x-dev|10.x-dev|dev-master
- phpunit/phpunit: ^9.5|^10.5
README
输送带
输送带提供了编写处理大量数据的高效 artisan 命令所需的全部底层机制。
快速处理数千条记录
必要时获取详细输出
需要时逐步执行并记录操作
查看您的命令更改了哪些数据
还有更多
安装
# composer require glhd/conveyor-belt
用法
要使用输送带,请在您的 Laravel 命令中使用输送带特质之一
数据库
\Glhd\ConveyorBelt\IteratesIdQuery— 如果您的底层查询可以按id排序(提高性能),请使用此功能\Glhd\ConveyorBelt\IteratesQuery— 如果您的查询 没有按id排序,请使用此功能
文件
\Glhd\ConveyorBelt\IteratesSpreadsheet— 使用此功能读取 CSV 或 Excel 文件\Glhd\ConveyorBelt\IteratesJson— 使用此功能读取 JSON 文件或 JSON API 数据
其他
\Glhd\ConveyorBelt\IteratesEnumerable— 使用此功能处理任何泛型数据源
配置
大多数命令可以通过在命令本身上设置公共属性进行配置。例如,如果您想启用异常处理,请将 public $collect_exceptions = true; 添加到您的命令中。每个配置选项也可以通过重写一个函数来管理(如果您需要对其值有更多动态控制)。查看每个特质源代码以找到适当的函数名称。
所有命令的通用设置
$collect_exceptions— 设置为true以在触发异常时继续运行您的命令(异常将在命令执行结束时打印出来)$row_name— 设置此值以自定义命令输出(例如,如果您正在操作User模型,可以将此设置为"user")$row_name_plural—$row_name的复数形式(通常不需要,因为我们为您使用Str::plural)
IteratesQuery
$chunk_size— 一次加载的数据库记录数$use_transaction— 是否在整个命令中运行数据库事务(如果您的命令运行时间过长,可能会导致锁定问题)
IteratesIdQuery
IteratesIdQuery 特质接受 IteratesQuery 的所有选项,以及
$id_column— 您的 ID 列名称(如果它不是"id")$id_alias— 您的查询中 ID 列的别名
IteratesSpreadsheet
$use_headings— 是否将每个工作表的第 1 行视为标题$preserve_empty_rows— 是否应包含空行$format_dates— 是否应格式化日期列(通常不需要此功能,因为输送带会自动将日期单元格转换为Carbon实例)$filename— 要加载的文件(仅在文件以任何方式动态时设置,这很少见)$excel_temp_directory— 如果需要,设置以自定义临时文件存储位置$field_delimiter— 如果需要导入非标准 CSV 文件(例如,制表符分隔的),则更改此值$field_enclosure— 如果需要导入非标准 CSV 文件(不使用"字符),则更改此值$spreadsheet_encoding— 如果您正在处理非 UTF-8 数据,则更改此值$heading_format— 将此更改为任何Str::函数以更改数组键的格式(默认为"snake")
IteratesJson
$filename— 要加载的文件(仅在文件以任何方式动态时设置,这很少见)$json_endpoint— 查询数据的 JSON 端点(使用getJsonEndpoint动态设置此端点)$json_pointer— 使用此指针迭代嵌套 JSON 数据(查看规范)
示例
数据库示例
class ProcessUnverifiedUsers extends Command { use \Glhd\ConveyorBelt\IteratesIdQuery; // By setting $collect_exceptions to true, we tell Conveyor Belt to catch // and log exceptions for display, rather than aborting execution public $collect_exceptions = true; // First, set up the query for the data that your command will operate on. // In this example, we're querying for all users that haven't verified their emails. public function query() { return User::query() ->whereNull('email_verified_at') ->orderBy('id'); } // Then, set up a handler for each row. Our example command is either going to // remind users to verify their email (if they signed up recently), or queue // a job to prune them from the database. public function handleRow(User $user) { // The `progressMessage()` method updates the progress bar in normal mode, // or prints the message in verbose/step mode $this->progressMessage("{$user->name} <{$user->email}>"); $days = $user->created_at->diffInDays(now()); // The `progressSubMessage()` method adds additional context. If you're in // normal mode, this gets appended to the `progressMessage()`. In verbose or // step mode, this gets added as a list item below your `progressMessage()` $this->progressSubMessage('Registered '.$days.' '.Str::plural('day', $days).' ago…'); // Sometimes our command trigger exceptions. Conveyor Belt makes it easy // to handle them and not have to lose all our progress ThirdParty::checkSomethingThatMayFail(); if (1 === $days) { $this->progressSubmessage('Sending reminder'); Mail::send(new EmailVerificationReminderMail($user)); } if ($days >= 7) { $this->progressSubmessage('Queuing to be pruned'); PruneUnverifiedUserJob::dispatch($user); } } }
文件示例
class ProcessSignUpSheet extends Command { use \Glhd\ConveyorBelt\IteratesSpreadsheet; // Conveyor Belt will automatically pick up a "filename" argument. If one // is missing you can set a $filename property or implement the getSpreadsheetFilename method protected $signature = 'process:sign-up-sheet {filename}'; public function handleRow($item) { // $item is an object keyed by the spreadsheet headings in snake_case, // so for example, the following CSV: // // Full Name, Sign Up Date, Email // Chris Morrell, 2022-01-02, chris@mailinator.com // // Will result in a full_name, sign_up_date, and email property // on the $item object. You can change from snake case to any other // string helper format by setting $heading_format } }
IteratesJson 特性与其 IteratesSpreadsheet 特性的工作方式完全相同,只是配置选项不同。