composer require ringlesoft/db-archive
php artisan vendor:publish --provider="RingleSoft\DbArchive\DbArchiveServiceProvider" --tag="config"
config/db-archive.php:
'connection' => 'mysql', // Your DB connection
'default_archive_table_suffix' => '_archive', // Suffix for archived tables
'archive_retention_days' => 30, // Default retention period
posts table (older than 30 days):
use RingleSoft\DbArchive\Facades\DbArchive;
DbArchive::archive('posts', now()->subDays(30));
config/db-archive.php (Configuration)app/Console/Kernel.php (Scheduling jobs)app/Models/ (Model-specific archiving logic)// Archive records older than 30 days in the 'orders' table
DbArchive::archive('orders', now()->subDays(30));
orders_archive table (if configured).Extend RingleSoft\DbArchive\Archivable trait in your model:
use RingleSoft\DbArchive\Archivable;
class Post extends Model
{
use Archivable;
protected $archiveRetentionDays = 90; // Override default
}
Then archive via:
Post::archiveOldRecords();
Add to app/Console/Kernel.php:
protected function schedule(Schedule $schedule)
{
$schedule->command('db-archive:run')->dailyAt('2:00');
}
Run via:
php artisan db-archive:run
Specify a custom suffix or table name:
DbArchive::archive('users', now()->subYear(), [
'archive_table' => 'user_history',
]);
Use softArchive to mark records as archived (instead of moving them):
DbArchive::softArchive('comments', now()->subDays(60));
DB::transaction(function () {
DbArchive::archive('transactions', now()->subMonth());
});
DbArchive::fake() in tests to mock archiving:
DbArchive::fake()->shouldArchive('posts', now()->subDays(30));
Foreign Key Conflicts:
DbArchive::archive() with skipForeignKeys: true (if supported).Large Tables:
chunk():
DB::table('logs')->where('created_at', '<', now()->subYear())
->chunk(1000, function ($records) {
DbArchive::archiveRecords($records, 'logs_archive');
});
Configuration Overrides:
$archiveRetentionDays) override global config.Soft Deletes:
SoftDeletes) may not archive correctly if deleted_at is not considered.DbArchive::archive('posts', now()->subDays(30), [
'where' => function ($query) {
$query->whereNull('deleted_at');
},
]);
Downtime:
Log Archiving: Enable debug mode in config:
'debug' => env('DB_ARCHIVE_DEBUG', false),
Logs will appear in storage/logs/laravel.log.
Dry Runs:
Use --dry-run flag in Artisan:
php artisan db-archive:run --dry-run
This simulates archiving without executing migrations.
Table Existence: If archiving fails with "table doesn't exist," manually create the archive table:
php artisan db-archive:create-archive-table posts
Custom Archive Logic: Override the archiving process by binding your own archiver:
$archiver = app()->make(\RingleSoft\DbArchive\Contracts\Archiver::class);
$archiver->archive($table, $cutoff, $options);
Pre/Post Archive Hooks: Publish and extend the package's views or listeners:
php artisan vendor:publish --provider="RingleSoft\DbArchive\DbArchiveServiceProvider" --tag="views"
Custom Archive Columns:
Add computed columns (e.g., archived_at) to archive tables by extending the ArchiveBuilder:
// In a service provider
$this->app->bind(\RingleSoft\DbArchive\Contracts\ArchiveBuilder::class, function () {
return new CustomArchiveBuilder();
});
Backup Strategy:
Combine with spatie/laravel-backup to backup archive tables separately:
Backup::create()->archiveTables(['posts_archive'])->storeOnDisk('backups');
connection in config matches the one used in your models ($connection property)._archive) if multiple packages use the same suffix.How can I help you explore Laravel packages today?