Skip to content

Commit 6f4be41

Browse files
feat: add console commands to back up tables
1 parent 2b53f11 commit 6f4be41

File tree

4 files changed

+192
-4
lines changed

4 files changed

+192
-4
lines changed

README.md

+12-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ composer require watheqalshowaiter/backup-tables
2525
Use the `BackupTables::generateBackup($tableToBackup)` Facade anywhere in your application and it will
2626
generate `$tableToBackup_backup_2024_08_22_17_40_01` table in the database with all the data and structure. Note that
2727
the datetime `2024_08_22_17_40_01` will be varied based on your datetime.
28+
29+
You can also use the `php artisan backup:tables <targets>` command to back up tables,
30+
where `<targets>` is a space-separated list of tables names or models.
2831

2932
```php
3033
use WatheqAlshowaiter\BackupTables\BackupTables; // import the facade
@@ -35,7 +38,7 @@ class ChangeSomeData
3538
{
3639
BackupTables::generateBackup('users'); // will result: users_backup_2024_08_22_17_40_01
3740

38-
// change some data..
41+
// change some data..
3942
}
4043
}
4144
```
@@ -75,6 +78,12 @@ BackupTables::generateBackup('users', 'Y_d_m_H'); // can not generate the same b
7578
BackupTables::generateBackup('users', 'Y_d_m'); // can not generate the same backup in the same day
7679
```
7780

81+
- Using the artisan command for one or more tables/models
82+
```bash
83+
php artisan backup:tables users posts # users_backup_2024_08_22_17_40_01, posts_backup_2024_08_22_17_40_01
84+
php artisan backup:tables \App\Models\User \App\Models\Post # users_backup_2024_08_22_17_40_01, posts_backup_2024_08_22_17_40_01
85+
```
86+
7887
## Why?
7988

8089
Sometimes you want to backup some database tables before changing data for whatever reason, this package serves this
@@ -84,6 +93,8 @@ beforehand.
8493

8594
## Features
8695

96+
✅ Backup tables from the code or from the console command.
97+
8798
✅ Supports Laravel versions: 11, 10, 9, 8, 7, and 6.
8899

89100
✅ Supports PHP versions: 8.2, 8.1, 8.0, and 7.4.

src/BackupTablesServiceProvider.php

+9-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace WatheqAlshowaiter\BackupTables;
44

55
use Illuminate\Support\ServiceProvider;
6+
use WatheqAlshowaiter\BackupTables\Commands\BackupTableCommand;
67

78
class BackupTablesServiceProvider extends ServiceProvider
89
{
@@ -13,9 +14,14 @@ public function register()
1314

1415
public function boot()
1516
{
16-
// This migration works only in the package test
17-
if ($this->app->runningInConsole() && $this->app->environment() === 'testing') {
18-
$this->loadMigrationsFrom(__DIR__.'/../tests/database/migrations');
17+
if ($this->app->runningInConsole()) {
18+
$this->commands([
19+
BackupTableCommand::class,
20+
]);
21+
22+
if($this->app->environment() === 'testing'){
23+
$this->loadMigrationsFrom(__DIR__.'/../tests/database/migrations');
24+
}
1925
}
2026
}
2127
}

src/Commands/BackupTableCommand.php

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
namespace WatheqAlshowaiter\BackupTables\Commands;
4+
5+
use Illuminate\Console\Command;
6+
use Symfony\Component\Console\Command\Command as CommandCodes;
7+
use WatheqAlshowaiter\BackupTables\BackupTables;
8+
9+
class BackupTableCommand extends Command
10+
{
11+
protected $signature = 'backup:tables {targets* : The table names or model classes to backup (space-separated)}';
12+
13+
protected $description = 'Backup a specific database table/s based on provided table names or model classes';
14+
15+
public function handle()
16+
{
17+
$tables = $this->argument('targets');
18+
19+
$tables = $this->getMultipleTables($tables);
20+
21+
try {
22+
$result = BackupTables::generateBackup($tables);
23+
24+
if (!$result) {
25+
$this->error('Failed to backup table.');
26+
return CommandCodes::FAILURE;
27+
}
28+
29+
return CommandCodes::SUCCESS;
30+
} catch (\Exception $e) {
31+
$this->error("Error backing up table: {$e->getMessage()}");
32+
return CommandCodes::FAILURE;
33+
}
34+
}
35+
36+
/**
37+
* @param $table
38+
*
39+
* @return false|string[]
40+
*/
41+
private function getMultipleTables($table)
42+
{
43+
$tablesArr = explode(' ', $table);
44+
45+
return array_filter($tablesArr, function ($item) {
46+
return !empty($item);
47+
});
48+
}
49+
}

tests/BackupTableCommandTest.php

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
<?php
2+
3+
namespace WatheqAlshowaiter\BackupTables\Tests;
4+
5+
use Illuminate\Foundation\Testing\RefreshDatabase;
6+
use Illuminate\Support\Facades\Schema;
7+
use WatheqAlshowaiter\BackupTables\Commands\BackupTableCommand;
8+
use WatheqAlshowaiter\BackupTables\Tests\Models\Father;
9+
use WatheqAlshowaiter\BackupTables\Tests\Models\Mother;
10+
11+
class BackupTableCommandTest extends TestCase
12+
{
13+
use RefreshDatabase;
14+
15+
/** @test */
16+
public function it_can_backup_a_table()
17+
{
18+
Schema::create('test_table', function ($table) {
19+
$table->id();
20+
$table->string('name');
21+
$table->timestamps();
22+
});
23+
24+
$this->artisan('backup:tables', ['targets' => 'test_table'])
25+
->assertSuccessful();
26+
27+
$backupTablePattern = 'test_table_backup_'.now()->format('Y_m_d_H_i_s');
28+
29+
$this->assertTrue(
30+
Schema::hasTable($backupTablePattern),
31+
"Backup table was not created"
32+
);
33+
}
34+
35+
/** @test */
36+
public function it_can_backup_a_table_by_classname()
37+
{
38+
Schema::create('test_table', function ($table) {
39+
$table->id();
40+
$table->string('name');
41+
$table->timestamps();
42+
});
43+
44+
$this->artisan(BackupTableCommand::class, ['targets' => 'test_table'])
45+
->assertSuccessful();
46+
47+
$backupTablePattern = 'test_table_backup_'.now()->format('Y_m_d_H_i_s');
48+
49+
$this->assertTrue(
50+
Schema::hasTable($backupTablePattern),
51+
"Backup table was not created"
52+
);
53+
}
54+
55+
/** @test */
56+
public function it_fails_when_table_does_not_exist()
57+
{
58+
$this->artisan('backup:tables', ['targets' => 'non_existent_table'])
59+
->assertFailed();
60+
}
61+
62+
/** @test */
63+
public function it_can_backup_multiple_tables()
64+
{
65+
$tables = ['test_table_1', 'test_table_2'];
66+
67+
foreach ($tables as $table) {
68+
Schema::create($table, function ($table) {
69+
$table->id();
70+
$table->string('name');
71+
$table->timestamps();
72+
});
73+
}
74+
75+
$this->artisan('backup:tables', ['targets' => implode(' ', $tables)])
76+
->assertSuccessful();
77+
78+
foreach ($tables as $table) {
79+
$backupTablePattern = $table.'_backup_'.now()->format('Y_m_d_H_i_s');
80+
81+
$this->assertTrue(
82+
Schema::hasTable($backupTablePattern),
83+
"Backup table was not created"
84+
);
85+
}
86+
87+
}
88+
89+
/** @test */
90+
public function it_can_backup_multiple_models()
91+
{
92+
$models = [Father::class, Mother::class];
93+
94+
$this->artisan('backup:tables', ['targets' => implode(' ', $models)])
95+
->assertSuccessful();
96+
97+
$backupTablePattern1 = 'fathers_backup_'.now()->format('Y_m_d_H_i_s');
98+
$backupTablePattern2 = 'mothers_backup_'.now()->format('Y_m_d_H_i_s');
99+
100+
$this->assertTrue(
101+
Schema::hasTable($backupTablePattern1),
102+
"Backup table was not created"
103+
);
104+
105+
$this->assertTrue(
106+
Schema::hasTable($backupTablePattern2),
107+
"Backup table was not created"
108+
);
109+
}
110+
111+
/** @test */
112+
public function it_fails_when_any_table_does_not_exist()
113+
{
114+
Schema::create('existing_table', function ($table) {
115+
$table->id();
116+
$table->timestamps();
117+
});
118+
119+
$this->artisan('backup:tables', ['targets' => 'existing_table non_existent_table'])
120+
->assertSuccessful();
121+
}
122+
}

0 commit comments

Comments
 (0)