aaronheath/laravel-model-copy

将一个Laravel Eloquent模型从一张表复制到另一张表。

1.1.1 2023-05-14 21:31 UTC

README

Latest Version on Packagist GitHub Tests Action Status Total Downloads

Laravel模型复制帮助您将记录从一个数据库表复制到另一个表。此解决方案旨在以安全的方式将不再需要的记录移动到另一个表,然后可以备份,如果需要,还可以截断。

该包还可以帮助执行使用与复制模型时相同的条件进行的批量模型删除。

安装

您可以通过composer安装此包

composer require aaronheath/laravel-model-copy

使用方法

该包可以通过以下三种方式之一使用

  • A) 复制或移动单个模型。
  • B) 使用查询批量复制或移动多个模型。
  • C) 使用查询批量删除模型。

复制或移动单个模型

复制单个模型就像...

<?php

use Heath\LaravelModelCopy\Action\CopyModel;
use App\Models\ExampleA;
use App\Models\ExampleB;

CopyModel::make()
    ->copy(Example::find(1))
    ->to(ExampleB::class)
    ->run();

复制单个模型并删除原始记录就像包括->deleteOriginal()

<?php

use Heath\LaravelModelCopy\Action\CopyModel;
use App\Models\ExampleA;
use App\Models\ExampleB;

CopyModel::make()
    ->copy(Example::find(1))
    ->to(ExampleB::class)
    ->deleteOriginal()
    ->run();

如果我们不希望在某个时间之后复制或移动模型,可以通过包括->processBefore(now()->addHour())来实现。

<?php

use Heath\LaravelModelCopy\Action\CopyModel;
use App\Models\ExampleA;
use App\Models\ExampleB;

CopyModel::make()
    ->copy(Example::find(1))
    ->to(ExampleB::class)
    ->processBefore(now()->addHour())
    ->run();

批量复制或移动多个模型

很可能您不会只想移动一条记录,这就是批量复制或移动发挥作用的地方。

以下是一个简单的批量复制示例,它将复制所有在handled_at中超过三年的模型ExampleA记录。

<?php

use Heath\LaravelModelCopy\Action\BatchCopyModels;
use App\Models\ExampleA;
use App\Models\ExampleB;

BatchCopyModels::make()
    ->to(ExampleB::class)
    ->query(
        ExampleA::where('handled_at', '<', now()->subYears(3))
    )
    ->run();

如果我们想删除原始模型,只需包括->deleteOriginal()即可。

<?php

use Heath\LaravelModelCopy\Action\BatchCopyModels;
use App\Models\ExampleA;
use App\Models\ExampleB;

BatchCopyModels::make()
    ->to(ExampleB::class)
    ->query(
        ExampleA::where('handled_at', '<', now()->subYears(3))
    )
    ->deleteOriginal()
    ->run();

如果我们想限制一次复制/移动的记录数量,可以使用->limit(1000)

<?php

use Heath\LaravelModelCopy\Action\BatchCopyModels;
use App\Models\ExampleA;
use App\Models\ExampleB;

BatchCopyModels::make()
    ->to(ExampleB::class)
    ->query(
        ExampleA::where('handled_at', '<', now()->subYears(3))
    )
    ->limit(1000)
    ->run();

默认情况下,查询将分批为100条记录。如果您想使用自己的分批值,可以使用->chunk(500)

<?php

use Heath\LaravelModelCopy\Action\BatchCopyModels;
use App\Models\ExampleA;
use App\Models\ExampleB;

BatchCopyModels::make()
    ->to(ExampleB::class)
    ->query(
        ExampleA::where('handled_at', '<', now()->subYears(3))
    )
    ->chunk(500)
    ->run();

要使用自定义(不是'ID')列进行分批,请使用->chunkColumn()

<?php

use Heath\LaravelModelCopy\Action\BatchCopyModels;
use App\Models\ExampleA;
use App\Models\ExampleB;

BatchCopyModels::make()
    ->to(ExampleB::class)
    ->query(
        ExampleA::where('handled_at', '<', now()->subYears(3))
    )
    ->chunk(500)
    ->chunkColumn('created_at')
    ->run();

到目前为止,所有操作都在一个同步流中发生。在现实世界的情况下,最好通过将单个复制/移动模型操作推送到队列来处理它们。这可以通过包括->copyModelsAsJobs()来实现。

<?php

use Heath\LaravelModelCopy\Action\BatchCopyModels;
use App\Models\ExampleA;
use App\Models\ExampleB;

BatchCopyModels::make()
    ->to(ExampleB::class)
    ->query(
        ExampleA::where('handled_at', '<', now()->subYears(3))
    )
    ->copyModelsAsJobs()
    ->run();

如果除了默认队列外还想使用其他队列,请包括->onQueue('queue-name')

<?php

use Heath\LaravelModelCopy\Action\BatchCopyModels;
use App\Models\ExampleA;
use App\Models\ExampleB;

BatchCopyModels::make()
    ->to(ExampleB::class)
    ->query(
        ExampleA::where('handled_at', '<', now()->subYears(3))
    )
    ->copyModelsAsJobs()
    ->onQueue('queue-name')
    ->run();

在移动大量数据时,可能需要相当长的时间。在这些情况下,您可能希望将移动批分组为时间块。例如,如果我们想在夜间23:00运行脚本,并确保在第二天05:00停止移动复制模型,可以使用->processBefore(now()->addDay()->setTime(5, 0, 0)

<?php

use Heath\LaravelModelCopy\Action\BatchCopyModels;
use App\Models\ExampleA;
use App\Models\ExampleB;

BatchCopyModels::make()
    ->to(ExampleB::class)
    ->query(
        ExampleA::where('handled_at', '<', now()->subYears(3))
    )
    ->copyModelsAsJobs()
    ->processBefore(now()->addDay()->setTime(5, 0, 0)) // 05:00 tomorrow
    ->run();

我们还可以限制在任何给定分钟内复制的记录数量。为此,可以定义每分钟的速率(rpm)。如果我们想确保每分钟只复制20条记录,则可以使用->rpm(20)。使用此功能需要使用->copyModelsAsJobs()

<?php

use Heath\LaravelModelCopy\Action\BatchCopyModels;
use App\Models\ExampleA;
use App\Models\ExampleB;

BatchCopyModels::make()
    ->to(ExampleB::class)
    ->query(
        ExampleA::where('handled_at', '<', now()->subYears(3))
    )
    ->copyModelsAsJobs()
    ->rpm(20)
    ->run();

实际示例

假设我们想将所有在handled_at中超过三年的记录移动到另一个表。我们只想运行到第二天06:00。我们还希望限制数据库负载,所以我们将每分钟只移动100条记录。要实现这一点,我们将使用以下...

<?php

use Heath\LaravelModelCopy\Action\BatchCopyModels;
use App\Models\ExampleA;
use App\Models\ExampleB;

BatchCopyModels::make()
    ->to(ExampleB::class)
    ->query(
        ExampleA::where('handled_at', '<', now()->subYears(3))
    )
    ->copyModelsAsJobs()
    ->processBefore(now()->addDay()->setTime(6, 0, 0)) // 06:00 tomorrow
    ->rpm(100)
    ->run();

删除单个模型

删除单个模型就像...

<?php

use Heath\LaravelModelCopy\Action\DeleteModel;
use App\Models\ExampleA;

DeleteModel::make()
    ->delete(ExampleA::find(1))
    ->run();

批量从查询中删除模型

很可能您不会只想删除一条记录,这就是批量删除发挥作用的地方。

这里是一个简单的批量删除操作,它会删除所有模型ExampleA中handled_at超过三年前的记录。

<?php

use Heath\LaravelModelCopy\Action\BatchDeleteModels;
use App\Models\ExampleA;

BatchDeleteModels::make()
    ->query(
        ExampleA::where('handled_at', '<', now()->subYears(3))
    )
    ->run();

如果我们想限制一次性删除的记录数量,可以使用->limit(1000)

<?php

use Heath\LaravelModelCopy\Action\BatchDeleteModels;
use App\Models\ExampleA;

BatchDeleteModels::make()
    ->query(
        ExampleA::where('handled_at', '<', now()->subYears(3))
    )
    ->limit(1000)
    ->run();

默认情况下,查询将分批为100条记录。如果您想使用自己的分批值,可以使用->chunk(500)

<?php

use Heath\LaravelModelCopy\Action\BatchDeleteModels;
use App\Models\ExampleA;

BatchDeleteModels::make()
    ->query(
        ExampleA::where('handled_at', '<', now()->subYears(3))
    )
    ->chunk(500)
    ->run();

要使用自定义(不是'ID')列进行分批,请使用->chunkColumn()

<?php

use Heath\LaravelModelCopy\Action\BatchDeleteModels;
use App\Models\ExampleA;

BatchDeleteModels::make()
    ->query(
        ExampleA::where('handled_at', '<', now()->subYears(3))
    )
    ->chunk(500)
    ->chunkColumn('created_at')
    ->run();

到目前为止,所有操作都在一个同步流中执行。在现实世界中,通过将单个模型删除操作推送到队列中处理,效果会更好。这可以通过包含->copyModelsAsJobs()来实现。

<?php

use Heath\LaravelModelCopy\Action\BatchDeleteModels;
use App\Models\ExampleA;

BatchDeleteModels::make()
    ->query(
        ExampleA::where('handled_at', '<', now()->subYears(3))
    )
    ->deleteModelsAsJobs()
    ->run();

如果除了默认队列外还想使用其他队列,请包括->onQueue('queue-name')

<?php

use Heath\LaravelModelCopy\Action\BatchDeleteModels;
use App\Models\ExampleA;

BatchDeleteModels::make()
    ->query(
        ExampleA::where('handled_at', '<', now()->subYears(3))
    )
    ->deleteModelsAsJobs()
    ->onQueue('queue-name')
    ->run();

在删除大量数据时可能需要相当长的时间。在这些情况下,您可能希望将删除批次分组到时间段中。比如说,我们想在每晚23:00运行脚本,并确保在第二天05:00停止移动删除模型。这可以通过使用->processBefore(now()->addDay()->setTime(5, 0, 0)来实现。

<?php

use Heath\LaravelModelCopy\Action\BatchDeleteModels;
use App\Models\ExampleA;

BatchCopyModels::make()
    ->query(
        ExampleA::where('handled_at', '<', now()->subYears(3))
    )
    ->deleteModelsAsJobs()
    ->processBefore(now()->addDay()->setTime(5, 0, 0)) // 05:00 tomorrow
    ->run();

我们可能还想限制在任何给定分钟内删除的记录数量。为此,可以定义每分钟的速率(rpm)。如果我们想确保每分钟只删除20条记录,则可以使用->rpm(20)。使用此功能需要使用->copyModelsAsJobs()

<?php

use Heath\LaravelModelCopy\Action\BatchDeleteModels;
use App\Models\ExampleA;

BatchDeleteModels::make()
    ->query(
        ExampleA::where('handled_at', '<', now()->subYears(3))
    )
    ->deleteModelsAsJobs()
    ->rpm(20)
    ->run();

测试

composer test

致谢

许可证

MIT许可证(MIT)。有关更多信息,请参阅许可证文件