Skip to content

Commit 9ee12f3

Browse files
Merge pull request #4 from WatheqAlshowaiter/feature/console-command
Feature/console command @coderabbitai
2 parents 2b53f11 + 70fb63d commit 9ee12f3

5 files changed

+199
-19
lines changed

README.md

+36-15
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010

1111
Backup single or multiple database tables with ease.
1212

13-
> Note: if you want a full database backup with many features go for [Spatie Laravel Backup](https://github.com/spatie/laravel-backup).
13+
> [!NOTE]
14+
> If you want a full database backup with many features, go
15+
> for [Spatie Laravel Backup](https://github.com/spatie/laravel-backup).
1416
1517
## Installation
1618

@@ -26,6 +28,9 @@ Use the `BackupTables::generateBackup($tableToBackup)` Facade anywhere in your a
2628
generate `$tableToBackup_backup_2024_08_22_17_40_01` table in the database with all the data and structure. Note that
2729
the datetime `2024_08_22_17_40_01` will be varied based on your datetime.
2830

31+
You can also use the `php artisan backup:tables <targets>` command to back up tables,
32+
where `<targets>` is a space-separated list of table names or models.
33+
2934
```php
3035
use WatheqAlshowaiter\BackupTables\BackupTables; // import the facade
3136

@@ -35,14 +40,14 @@ class ChangeSomeData
3540
{
3641
BackupTables::generateBackup('users'); // will result: users_backup_2024_08_22_17_40_01
3742

38-
// change some data..
43+
// change some data..
3944
}
4045
}
4146
```
4247

4348
And More Customizations
4449

45-
- You can use an array to backup more than one table
50+
- You can use an array to back up more than one table
4651

4752
```php
4853
BackupTables::generateBackup(['users', 'posts']);
@@ -55,7 +60,8 @@ BackupTables::generateBackup(['users', 'posts']);
5560
```php
5661
BackupTables::generateBackup(User::class); // users_backup_2024_08_22_17_40_01
5762
// or
58-
BackupTables::generateBackup([User::class, Post::class]); // users_backup_2024_08_22_17_40_01, posts_backup_2024_08_22_17_40_01
63+
BackupTables::generateBackup([User::class, Post::class]); //-php artisan backup:tables users posts # users_backup_2024_08_22_17_40_01, posts_backup_2024_08_22_17_40_01
64+
users_backup_2024_08_22_17_40_01, posts_backup_2024_08_22_17_40_01
5965

6066
```
6167

@@ -65,25 +71,38 @@ BackupTables::generateBackup([User::class, Post::class]); // users_backup_2024_0
6571
BackupTables::generateBackup('users', 'Y_d_m_H_i'); // users_backup_2024_22_08_17_40
6672
```
6773

68-
> *Note: be aware if you customize the datetime to wide datetime the package will check the backup datetime file and
69-
> will be skipped
70-
> the exact same datetime, so most of the time the default will be fine
71-
> For example: if you use this `Y_d_m_H` you can not generate the same backup in the same hour
74+
> [!WARNING]
75+
> When customizing the datetime format, be aware that backups with identical datetime values will be skipped.
76+
> For example, if you use this `Y_d_m_H` you cannot generate the same backup in the same hour.
77+
> The default format (Y_m_d_H_i_s) is recommended for most cases.
7278
7379
```php
7480
BackupTables::generateBackup('users', 'Y_d_m_H'); // can not generate the same backup in the same hour
7581
BackupTables::generateBackup('users', 'Y_d_m'); // can not generate the same backup in the same day
7682
```
7783

84+
- Using the artisan command for one or more tables/models
85+
86+
```bash
87+
php artisan backup:tables users posts # users_backup_2024_08_22_17_40_01, posts_backup_2024_08_22_17_40_01
88+
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
89+
```
90+
7891
## Why?
7992

80-
Sometimes you want to backup some database tables before changing data for whatever reason, this package serves this
81-
need. I used it personally before adding foreign keys for tables that required the removal of unlinked fields for parent tables.
82-
You may find some situation where you play with table data or you're afraid of missing data so you backup these tables
93+
Sometimes you want to back up some database tables before changing data for whatever reason, this package serves this
94+
need.
95+
96+
I used it personally before adding foreign keys to tables that required removing unlinked fields from parent tables.
97+
98+
You may find some situation where you play with table data, or you're afraid of missing data, so you back up these
99+
tables
83100
beforehand.
84101

85102
## Features
86103

104+
✅ Backup tables from the code using (Facade) or from the console command.
105+
87106
✅ Supports Laravel versions: 11, 10, 9, 8, 7, and 6.
88107

89108
✅ Supports PHP versions: 8.2, 8.1, 8.0, and 7.4.
@@ -102,11 +121,15 @@ composer test
102121

103122
## Changelog
104123

105-
Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.
124+
Please see [CHANGELOG](CHANGELOG.md) for more information on recent changes.
106125

107126
## Contributing
108127

109-
If you have any ideas or suggestions to improve it or fix bugs, your contribution is welcome. I encourage you to look at [todos](./todos.md) which are the most important features that need to be added. If you have something different, submit an issue first to discuss or report a bug, then do a pull request.
128+
If you have any ideas or suggestions to improve it or fix bugs, your contribution is welcome.
129+
130+
I encourage you to look at [todos](./todos.md) which are the most important features that need to be added.
131+
132+
If you have something different, submit an issue first to discuss or report a bug, then do a pull request.
110133

111134
## Security Vulnerabilities
112135

@@ -118,11 +141,9 @@ them.
118141
- [Watheq Alshowaiter](https://github.com/WatheqAlshowaiter)
119142
- [Omar Alalwi](https://github.com/omaralalwi) - This package is based on his initial code.
120143
- [All Contributors](../../contributors)
121-
122144

123145
And a special thanks to [The King Creative](https://www.facebook.com/thkingcreative) for the logo ✨
124146

125-
126147
## License
127148

128149
The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

src/BackupTablesService.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ protected function returnedBackupResponse($newTableName, $table): array
111111
'newCreatedTables' => "Newly created table: $newTableName",
112112
];
113113

114-
// to prevent duplicating message if you use generateBackup() twice in the same request event for different tables
114+
// to prevent a duplicating message if you use generateBackup() twice in the same request event for different tables
115115
Arr::forget($this->response, '0');
116116

117117
return $result;

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

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

tests/BackupTableCommandTest.php

+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
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->bigIncrements('id');
20+
$table->string('name');
21+
$table->timestamps();
22+
});
23+
24+
$this->artisan('backup:tables', ['targets' => 'test_table'])
25+
->assertExitCode(BackupTableCommand::SUCCESS);
26+
27+
$backupTablePattern = 'test_table_backup_'.now()->format('Y_m_d_H_i_s');
28+
29+
$this->assertTrue(Schema::hasTable($backupTablePattern));
30+
}
31+
32+
/** @test */
33+
public function it_can_backup_a_table_by_classname()
34+
{
35+
Schema::create('test_table', function ($table) {
36+
$table->bigIncrements('id');
37+
$table->string('name');
38+
$table->timestamps();
39+
});
40+
41+
$this->artisan(BackupTableCommand::class, ['targets' => 'test_table'])
42+
->assertExitCode(BackupTableCommand::SUCCESS);
43+
44+
$backupTablePattern = 'test_table_backup_'.now()->format('Y_m_d_H_i_s');
45+
46+
$this->assertTrue(Schema::hasTable($backupTablePattern));
47+
}
48+
49+
/** @test */
50+
public function it_fails_when_table_does_not_exist()
51+
{
52+
$this->artisan('backup:tables', ['targets' => 'non_existent_table'])
53+
->assertExitCode(BackupTableCommand::FAILURE);
54+
}
55+
56+
/** @test */
57+
public function it_can_backup_multiple_tables()
58+
{
59+
$tables = ['test_table_1', 'test_table_2'];
60+
61+
foreach ($tables as $table) {
62+
Schema::create($table, function ($table) {
63+
$table->bigIncrements('id');
64+
$table->string('name');
65+
$table->timestamps();
66+
});
67+
}
68+
69+
$this->artisan('backup:tables', ['targets' => $tables])
70+
->assertExitCode(BackupTableCommand::SUCCESS);
71+
72+
foreach ($tables as $table) {
73+
$backupTablePattern = $table.'_backup_'.now()->format('Y_m_d_H_i_s');
74+
75+
$this->assertTrue(Schema::hasTable($backupTablePattern));
76+
}
77+
78+
}
79+
80+
/** @test */
81+
public function it_can_backup_multiple_models()
82+
{
83+
$models = [Father::class, Mother::class];
84+
$now = now();
85+
86+
$this->artisan('backup:tables', ['targets' => $models])
87+
->assertExitCode(BackupTableCommand::SUCCESS);
88+
89+
$backupTablePattern1 = 'fathers_backup_'.$now->format('Y_m_d_H_i_s');
90+
$backupTablePattern2 = 'mothers_backup_'.$now->format('Y_m_d_H_i_s');
91+
92+
$this->assertTrue(Schema::hasTable($backupTablePattern1));
93+
94+
$this->assertTrue(Schema::hasTable($backupTablePattern2));
95+
}
96+
97+
/** @test */
98+
public function it_fails_when_any_table_does_not_exist_but_saves_corrected_tables()
99+
{
100+
Schema::create('existing_table', function ($table) {
101+
$table->bigIncrements('id');
102+
$table->timestamps();
103+
});
104+
105+
$this->artisan('backup:tables', ['targets' => 'existing_table', 'non_existent_table'])
106+
->assertExitCode(BackupTableCommand::SUCCESS);
107+
108+
$backupExistingTablePattern = 'existing_table_backup_'.now()->format('Y_m_d_H_i_s');
109+
$backupNonExistingTablePattern = 'non_existent_table_backup_'.now()->format('Y_m_d_H_i_s');
110+
111+
$this->assertTrue(Schema::hasTable($backupExistingTablePattern));
112+
113+
$this->assertFalse(Schema::hasTable($backupNonExistingTablePattern));
114+
}
115+
}

0 commit comments

Comments
 (0)