Carga de seeders de forma configurable en Laravel

Spread the love

En alguna ocasión cuando estoy haciendo trabajo de refactorización y me dispongo a agregar un seeder me a tocado toparme con un DatabaseSeeder como el siguiente.

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        if (app()->environment() == 'production') {
            //$this->call(ThemesSeed::class);
            //$this->call(LanguagesSeed::class);
            $this->call(PlaceSeed::class);

        } else {
            $this->call(UserSeed::class);
            //$this->call(ModuleSeed::class);
            //$this->call(ThemeSeed::class);
            $this->call(LanguageSeed::class);
            $this->call(PlaceSeed::class);
           //....
        }
    }
}

A pasar de que el DatabaseSeeder se puede ejecutar dependiendo del ambiente que quieres, necesitas comentar lo que no requieres que se ejecute nuevamente.

por otro lado si agregas mas ambientes, tienes que ampliar el numero de condiciones que tienes en el DatabaseSeeder,

y por ultimo, tener código que no utilizas comentado, siempre ensucia el código.

Así que para este caso vamos a aprovechar el uso de los archivos de configuración y las colecciones para crear un seeder mas ameno a la vista y mas funcional.

Seeder

Creando la configuración

Una forma sencilla de tener esto un poco mas ordenado es crear un archivo de configuración en app/config donde puedas indicar que ambiente y que seeder quiere cargar.

Utiliza el config.

Así que podemos crear un archivo app/config/seeders.php y trasladar todo lo que tenemos en las condiciones a un arreglo de la siguiente forma.

return [
    'production' => [
        ['name' => ThemesSeed::class,        'callable' => false],
        ['name' =>LanguagesSeed::class,   'callable' => false],
        ['name' => PlaceSeed::class,       'callable' => true],
        
    ],

    'local' => [
        ['name' => UserSeed::class,        'callable' => false],
        ['name' => EvaluationSeed::class,  'callable' => false],
        ['name' => GeneratorSeed::class,   'callable' => false],
        ['name' => IdentitySeed::class,    'callable' => false],
        ['name' => PlaceSeed::class,       'callable' => true],
        ['name' => ProfileSeed::class,     'callable' => false],
        ['name' => SubjectSeed::class,     'callable' => false],
        ['name' => TelephoneSeed::class,   'callable' => false],
        ['name' => AddressSeed::class,     'callable' => false],
        ['name' => ModuleSeed::class,      'callable' => true],
        ['name' => ThemeSeed::class,       'callable' => true],
        ['name' => LanguageSeed::class,    'callable' => true],
        ['name' => ScheduleSeed::class,    'callable' => true],
    ],
];

El arreglo esta organizado por «ambientes» y los seeders se cargan siempre que estén en true. Con este cambio solo tenemos que modificar el DatabaseSeeder, para que solo cargue lo necesario.

Aprovechando las colecciones

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::statement('SET FOREIGN_KEY_CHECKS=0;');

        collect(config('seeders')[app()->environment()])
            ->where('callable', true)
            ->each(function ($seeder){
                $this->call($seeder['name']);
            });

        DB::statement('SET FOREIGN_KEY_CHECKS=1;');
    }
}

Y con esto ya quedo listo todo, ya puedes indicar el seeder que quieres cargar de acuerdo a tu ambiente y agregar uno nuevosolo requiere cambiar el config sin necesidad de cambiar el DatabaseSeeder.

Conclusión

Espero que les sea de utilidad la idea, y si tienen alguna otra forma de hacer esto cuéntanos dejando tus comentarios y recuerden compartir!.