glhd/conveyor-belt

2.1.0 2024-03-12 20:00 UTC

This package is auto-updated.

Last update: 2024-09-12 20:56:47 UTC


README

Build Status Coverage Status Latest Stable Release MIT Licensed Follow @inxilpro on Twitter

输送带

输送带提供了编写处理大量数据的高效 artisan 命令所需的全部底层机制。

快速处理数千条记录

Screencast of default behavior

必要时获取详细输出

Screencast of verbose behavior

需要时逐步执行并记录操作

Screencast of step behavior

查看您的命令更改了哪些数据

Screencast of diff behavior

还有更多

Screencast of help view

安装

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