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
特性的工作方式完全相同,只是配置选项不同。