Skip to content

Commit

Permalink
seeders #61 (#62)
Browse files Browse the repository at this point in the history
* Create `faker-seeders` command

* Include a section in the README for the Faker seeders command
  • Loading branch information
cable8mm authored Apr 3, 2024
1 parent c3ef928 commit 7feccb1
Show file tree
Hide file tree
Showing 9 changed files with 349 additions and 0 deletions.
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,26 @@ bin/console seeders -f -t xeeds
# Force to generate a seeder from `xeeds` table in `dist/database/seeders` folder
```

### Generate `Faker Seeders`

The Faker seeders are utilized without the `factory()` method to generate seeds. This command was created to address the issue, providing insight into its purpose.

```shell tab=Laravel
php artisan xeed:faker-seeders
# Generate all seeds from database in `database/seeders` folder

php artisan xeed:faker-seeders -f -t xeeds
# Force to generate a seeder from `xeeds` table in `database/seeders` folder
```

```shell tab=Standalone
bin/console faker-seeders
# Generate all seeds from database in `dist/database/seeders` folder

bin/console faker-seeders -f -t xeeds
# Force to generate a seeder from `xeeds` table in `dist/database/seeders` folder
```

### Generate `DatabaseSeeder`

```shell tab=Laravel
Expand Down Expand Up @@ -257,6 +277,10 @@ bin/console xeed drop
Utilize migration files for all database field types by referring to the following location `database/*.sql` these files are saved in the specified folder.
### Use `testorchestral/testbench`
You can utilize `testorchestral/testbench` to execute tests. When running Laravel commands, the generated files are saved in the `vendor/orchestra/testbench-core/laravel/database` folder.
## Credits
- [Samgu Lee](https://github.com/cable8mm)
Expand Down
2 changes: 2 additions & 0 deletions bin/console
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require __DIR__.'/../vendor/autoload.php';
use Cable8mm\Xeed\Command\CleanCommand;
use Cable8mm\Xeed\Command\GenerateDatabaseSeederCommand;
use Cable8mm\Xeed\Command\GenerateFactoriesCommand;
use Cable8mm\Xeed\Command\GenerateFakerSeedersCommand;
use Cable8mm\Xeed\Command\GenerateMigrationsCommand;
use Cable8mm\Xeed\Command\GenerateModelsCommand;
use Cable8mm\Xeed\Command\GenerateSeedersCommand;
Expand All @@ -23,5 +24,6 @@ $application->add(new ImportXeedCommand());
$application->add(new CleanCommand());
$application->add(new GenerateFactoriesCommand());
$application->add(new GenerateMigrationsCommand());
$application->add(new GenerateFakerSeedersCommand());

$application->run();
78 changes: 78 additions & 0 deletions src/Command/GenerateFakerSeedersCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

namespace Cable8mm\Xeed\Command;

use Cable8mm\Xeed\Generators\FakerSeederGenerator;
use Cable8mm\Xeed\Support\Path;
use Cable8mm\Xeed\Xeed;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

/**
* Generate seeders.
*
* Run `bin/console generate-seeders` or `bin/console seeders`
*/
#[AsCommand(
name: 'generate-faker-seeders',
description: 'Generate faker seeders. run `bin/console generate-faker-seeders` or `bin/console fakers`',
hidden: false,
aliases: ['faker-seeders', 'fakers', 'faker']
)]
class GenerateFakerSeedersCommand extends Command
{
/**
* Configure the command.
*/
protected function configure(): void
{
$dotenv = \Dotenv\Dotenv::createImmutable(getcwd());
$dotenv->safeLoad();

$this
->addOption(
'force',
'f',
InputOption::VALUE_OPTIONAL,
'Are files forcibly deleted even if they exist?',
false
)->addOption(
'table',
't',
InputOption::VALUE_OPTIONAL,
'Are you generating the specific table with the faker seed?',
null
);
}

/**
* Run the console command.
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$force = $input->getOption('force') ?? true;

$table = $input->getOption('table');

$tables = is_null($table)
? Xeed::getInstance()->attach()->getTables()
: Xeed::getInstance()->attach($table)->getTables();

foreach ($tables as $table) {
try {
FakerSeederGenerator::make($table)->run(force: $force);

$output->writeln('<info>'.Path::seeder().DIRECTORY_SEPARATOR.$table->seeder().'.php have been generated.'.'</info>');
} catch (\RuntimeException $e) {
$output->writeln('<error>'.Path::seeder().DIRECTORY_SEPARATOR.$table->seeder().'.php file already exists.'.'</error>');
}
}

$output->writeln('<info>generate-faker-seeders</info> command executed successfully.');

return Command::SUCCESS;
}
}
91 changes: 91 additions & 0 deletions src/Generators/FakerSeederGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

namespace Cable8mm\Xeed\Generators;

use Cable8mm\Xeed\Interfaces\GeneratorInterface;
use Cable8mm\Xeed\Support\File;
use Cable8mm\Xeed\Support\Path;
use Cable8mm\Xeed\Table;

/**
* Generator for `dist/database/seeders/*.php`.
*/
final class FakerSeederGenerator implements GeneratorInterface
{
/**
* @var string Stub string from the stubs folder file.
*/
private string $stub;

/**
* The left padding for the body of the generated.
*/
const INTENT = ' ';

const SUB_INTENT = ' ';

private int $count = 10;

private function __construct(
private Table $table,
private ?string $namespace = null,
private ?string $destination = null
) {
if (is_null($destination)) {
$this->destination = Path::seeder();
}

if (is_null($namespace)) {
$this->namespace = '\App\Models';
}

$this->stub = File::system()->read(Path::stub().DIRECTORY_SEPARATOR.'FakerSeeder.stub');
}

/**
* Set count values for the generated stub
*/
public function count(int $count): static
{
$this->count = $count;

return $this;
}

/**
* {@inheritDoc}
*/
public function run(bool $force = false): void
{
$record = self::SUB_INTENT.'$records[] = ['.PHP_EOL;

foreach ($this->table->getColumns() as $column) {
$record .= self::INTENT.$column->fake().PHP_EOL;
}

$record = preg_replace('/\n$/', '', $record).PHP_EOL.self::SUB_INTENT.'];';

$seederClass = str_replace(
['{class}', '{records}', '{table_name}', '{count}'],
[$this->table->model('Seeder'), $record, $this->table, $this->count],
$this->stub
);

File::system()->write(
$this->destination.DIRECTORY_SEPARATOR.$this->table->seeder('.php'),
$seederClass,
$force
);
}

/**
* {@inheritDoc}
*/
public static function make(
Table $table,
?string $namespace = null,
?string $destination = null
): static {
return new self($table, $namespace, $destination);
}
}
66 changes: 66 additions & 0 deletions src/Laravel/Commands/GenerateFakerSeedersCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

namespace Cable8mm\Xeed\Laravel\Commands;

use Cable8mm\Xeed\Generators\FakerSeederGenerator;
use Cable8mm\Xeed\Xeed;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

class GenerateFakerSeedersCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'xeed:faker-seeders
{--f|force : Are files forcibly deleted even if they exist?}
{--t|table= : Are you generating the specific table with the faker seeder?}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Generate faker seeders from your own database tables';

protected function configure()
{
$this->setAliases([
'xeed:fakers',
'xeed:faker',
]);

parent::configure();
}

/**
* Execute the console command.
*/
public function handle(Xeed $xeed)
{
$force = $this->option('force') ?? false;

$table = $this->option('table');

$tables = is_null($table)
? $xeed->addPdo(DB::connection()->getPDO())->attach()->getTables()
: $xeed->addPdo(DB::connection()->getPDO())->attach($table)->getTables();

foreach ($tables as $table) {
try {
FakerSeederGenerator::make(
$table,
destination: database_path('seeders')
)->run(force: $force);

$this->info(database_path('seeders').DIRECTORY_SEPARATOR.$table->seeder().'.php has been generated.');
} catch (\Exception $e) {
$this->error(database_path('seeders').DIRECTORY_SEPARATOR.$table->seeder().'.php file already exists.');
}
}

return Command::SUCCESS;
}
}
2 changes: 2 additions & 0 deletions src/Laravel/XeedServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Cable8mm\Xeed\Laravel\Commands\CleanCommand;
use Cable8mm\Xeed\Laravel\Commands\GenerateDatabaseSeederCommand;
use Cable8mm\Xeed\Laravel\Commands\GenerateFactoriesCommand;
use Cable8mm\Xeed\Laravel\Commands\GenerateFakerSeedersCommand;
use Cable8mm\Xeed\Laravel\Commands\GenerateMigrationsCommand;
use Cable8mm\Xeed\Laravel\Commands\GenerateModelsCommand;
use Cable8mm\Xeed\Laravel\Commands\GenerateSeedersCommand;
Expand All @@ -30,6 +31,7 @@ public function boot()
GenerateSeedersCommand::class,
ImportXeedCommand::class,
CleanCommand::class,
GenerateFakerSeedersCommand::class,
]);
}
}
Expand Down
25 changes: 25 additions & 0 deletions stubs/FakerSeeder.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

class {class} extends Seeder
{
/**
* Run the database seeds without factory.
*/
public function run(): void
{
DB::table('{table_name}')->truncate();

$records = [];

for ($i = 0; $i < {count}; $i++) {
{records}
}

DB::table('{table_name}')->insert($records);
}
}
28 changes: 28 additions & 0 deletions tests/Laravel/Commands/GenerateFakerSeedersCommandTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Cable8mm\Xeed\Tests\Laravel\Commands;

class GenerateFakerSeedersCommandTest extends \Orchestra\Testbench\TestCase
{
public function test_execute_xeed_database_command()
{
$this->artisan('xeed:faker-seeders')->assertSuccessful();
}

public function test_execute_xeed_database_command_with_table()
{
$this->artisan('xeed:faker-seeders -t xeeds')->assertSuccessful();
}

public function test_execute_xeed_database_alias_command_with_table()
{
$this->artisan('xeed:faker -t xeeds')->assertSuccessful();
}

protected function getPackageProviders($app)
{
return [
'Cable8mm\Xeed\Laravel\XeedServiceProvider',
];
}
}
33 changes: 33 additions & 0 deletions tests/Unit/Generators/FakerSeederGeneratorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Cable8mm\Xeed\Tests\Unit\Generators;

use Cable8mm\Xeed\Column;
use Cable8mm\Xeed\Generators\FakerSeederGenerator;
use Cable8mm\Xeed\Support\File;
use Cable8mm\Xeed\Support\Path;
use Cable8mm\Xeed\Table;
use PHPUnit\Framework\TestCase;

final class FakerSeederGeneratorTest extends TestCase
{
protected function setUp(): void
{
FakerSeederGenerator::make(
new Table('samples', [
Column::make('id', 'bigint'),
]),
destination: Path::testgen()
)->run();
}

protected function tearDown(): void
{
// File::system()->delete(Path::testgen().DIRECTORY_SEPARATOR.'SampleSeeder.php');
}

public function test_it_can_can_generate_seeder_file(): void
{
$this->assertFileExists(Path::testgen().DIRECTORY_SEPARATOR.'SampleSeeder.php');
}
}

0 comments on commit 7feccb1

Please sign in to comment.