nexusbrother/laravel-archivable

This is laravel extension packages

Maintainers

Package info

github.com/nexusbrother/laravel-archivable

pkg:composer/nexusbrother/laravel-archivable

Transparency log

Statistics

Installs: 13

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 1

1.0.1 2026-07-16 08:18 UTC

This package is auto-updated.

Last update: 2026-07-16 16:34:53 UTC


README

Laravel Archivable 是一个数据库记录归档扩展包,能够将过期记录从主库自动迁移到独立的归档数据库,同时保持表结构同步。

功能特性

  • 📦 将模型记录归档到独立的归档数据库
  • 🔄 自动同步主库与归档库之间的表结构(新增/修改字段、索引)
  • 📅 支持基于日期字段的自动归档(DateFieldArchivable
  • 🗓️ 支持按月自动分表归档(MonthlyArchivable
  • ⚡ 批量归档,可配置 chunk 大小,支持外键约束自动处理
  • 📊 命令行归档时显示实时进度条
  • 🔔 归档完成触发 ModelsArchived 事件,方便自定义后续逻辑
  • ⏰ 内置定时任务调度,可配置执行时间

安装

composer require nexusbrother/laravel-archivable

发布配置文件:

php artisan vendor:publish --provider="Nexusbrother\Archivable\ServiceProvider" --tag="config"

配置

1. 数据库连接

config/database.phpconnections 中添加 archive 连接:

'archive' => [
    'driver'   => 'mysql',
    'host'     => env('ARCHIVE_DB_HOST', '127.0.0.1'),
    'port'     => env('ARCHIVE_DB_PORT', '3306'),
    'database' => env('ARCHIVE_DB_DATABASE', 'archive'),
    'username' => env('ARCHIVE_DB_USERNAME', 'root'),
    'password' => env('ARCHIVE_DB_PASSWORD', ''),
    'charset'  => 'utf8mb4',
    'collation'=> 'utf8mb4_unicode_ci',
    'prefix'   => '',
    'strict'   => true,
    'engine'   => null,
],

2. 环境变量

# 启用定时归档任务(默认 false)
ARCHIVE_ENABLE=true

# 归档数据库连接名(默认 archive)
ARCHIVE_DB_CONNECTION=archive

# 定时任务执行时间
ARCHIVE_SCHEDULE_STRUCTURE_SYNC_DAILY_AT=09:00
ARCHIVE_SCHEDULE_ARCHIVE_DAILY_AT=09:10

3. 配置项

config/archive.php

return [
    // 是否启用定时归档任务
    'enable' => env('ARCHIVE_ENABLE', false),

    // 定时任务执行时间
    'schedule_daily_at' => [
        'archive_structure_sync' => '09:00',  // 表结构同步
        'archive'                => '09:10',  // 数据归档
    ],

    // 每批处理的记录数
    'default_chunk_size' => 1000,

    // 归档数据库连接名
    'db' => env('ARCHIVE_DB_CONNECTION', 'archive'),

    // 自动扫描 Archivable 模型的目录
    'model_paths' => [
        app_path('Models'),
    ],
];

使用方法

1. 基于日期字段归档(DateFieldArchivable)

适合按时间归档的场景,所有记录归档到同一张目标表

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Nexusbrother\Archivable\DateFieldArchivable;

class Order extends Model
{
    use DateFieldArchivable;

    /**
     * 可选:自定义日期字段(默认 created_at)
     */
    public function getDateField(): string
    {
        return 'created_at';
    }

    /**
     * 可选:自定义归档时间界限(默认 6 个月前)
     */
    public function getDateLimit()
    {
        return today()->subYear();
    }

    /**
     * 可选:自定义归档目标表名(默认与源表同名)
     */
    public function getDestinationTable(): string
    {
        return $this->getTable() . '_' . now()->format('Ym');
    }
}

2. 按月分表归档(MonthlyArchivable)

适合日志、消息等按月分区的数据,每个月的记录归档到独立的月表(如 logs_202501logs_202502):

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Nexusbrother\Archivable\MonthlyArchivable;

class Log extends Model
{
    use MonthlyArchivable;

    /**
     * 可选:自定义日期字段(默认 created_at)
     */
    public function getDateField(): string
    {
        return 'created_at';
    }

    /**
     * 可选:归档多少个月之前的数据(默认 6 个月)
     */
    public function getArchiveMonthLimit()
    {
        return today()->subMonths(3);
    }
}

3. 自定义归档条件(Archivable)

完全自定义归档逻辑:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Nexusbrother\Archivable\Archivable;

class User extends Model
{
    use Archivable;

    /**
     * 定义可归档的记录查询
     */
    public function archivable()
    {
        return $this->where('last_login_at', '<', now()->subYear());
    }

    /**
     * 可选:自定义归档目标表
     */
    public function getDestinationTable(): string
    {
        return 'archived_users';
    }
}

命令行

表结构同步

归档前先同步表结构,确保归档表存在且字段一致:

# 同步所有 Archivable 模型
php artisan model:archive-structure-sync

# 指定模型
php artisan model:archive-structure-sync --model="App\Models\Order"

# 排除模型
php artisan model:archive-structure-sync --except="App\Models\User"

数据归档

# 归档所有已注册模型
php artisan model:archive

# 指定模型
php artisan model:archive --model="App\Models\Order" --model="App\Models\Log"

# 排除模型
php artisan model:archive --except="App\Models\User"

# 自定义 chunk 大小
php artisan model:archive --chunk=500

# 仅预览,不执行
php artisan model:archive --pretend

执行时会显示实时进度条:

 4532/50000 [▓▓▓░░░░░░░░░░░░░░░░░]  9%

编程方式使用

// 归档单个记录
$order->archive();

// 归档所有符合条件的记录
$order->archiveAll();

// 自定义 chunk 大小
$order->archiveAll(500);

// 带进度回调(每处理完一个 chunk 触发)
$order->archiveAll(1000, function (int $chunkCount) {
    // 处理了 $chunkCount 条记录
});

// 带开始回调和进度回调
$order->archiveAll(1000, function (int $chunkCount) {
    // 每批完成
}, function (int $total) {
    // 开始归档,共 $total 条待处理
});

事件

归档完成后触发 ModelsArchived 事件:

use Illuminate\Support\Facades\Event;
use Nexusbrother\Archivable\ModelsArchived;

Event::listen(ModelsArchived::class, function (ModelsArchived $event) {
    // $event->model  被归档的模型类名
    // $event->count  归档的记录数量

    Log::info("Archived {$event->count} records from {$event->model}");
});

定时任务

包内置两个定时任务,在 config('archive.enable')true 时自动注册:

任务 默认时间 说明
model:archive-structure-sync 09:00 同步所有 Archivable 模型的归档表结构
model:archive 09:10 执行数据归档

两个任务均配置了 onOneServer()withoutOverlapping(),适合多服务器部署。

系统要求

  • PHP >= 8.1
  • Laravel 9 / 10 / 11

许可证

MIT License