Aprende eloquent con ejemplos!!! - Lección 2: Faker, Factories, Seeders
Johan Tovar
Posted on April 19, 2021
En la entrega primera entrega de Aprende eloquent con ejemplos!!!, vimos como crear y usar de una manera bastante básica nuestras migraciones y seeders, por lo que en esta lección les enseñaré como podemos darle un mejor uso y hacer que trabajen de manera integral de cara a un flujo de trabajo más eficiente en nuestro desarrollo, para ello, aprenderemos sobre:
- Factories
- Faker
Empezaremos con destruir nuestra migración hecha en la lección pasada, pero debes recordar que aunque podemos ir y borrar nuestro archivo migrations
, eso nos causaría muchas dificultades y molestias, razón por la cual debes proceder a ejecutar en consola el comando:
php artisan migrate:rollback
De esta manera regresaríamos nuestra base de datos a su estado inicial, eliminando la tabla dogs
registrada anteriormente. Hecho esto, podemos ahora si proceder a borrar nuestro archivo migrations
sin temor de dificultades, vayamos al directorio respectivo y eliminar el archivo <timestamp>_create_table_dogs
.
Con
rollback
devolvimos todas las migraciones ejecutadas, pudimos haber usado el flag--step=1
y solo eliminar nuestra tabledogs
dejando las demás intactas. Recuerda que el comandomigrate
tiene varias opciones, tomate tu tiempo para repasarlas y probar con ellas.
En este momento tenemos nuestra base de datos y migraciones en su estado inicial, así que ya podemos dar inicio con nuestra lección. En este sentido, y como una necesidad para poder trabajar con los elementos listados mas arriba, debemos abordar primero un concepto fundamental dentro del mundo de eloquent, el cual paso de seguida a explicarte de que se trata.
Conociendo los Modelos
En la pasada lección creamos una tabla y luego insertamos datos en ella a través de nuestro seeder, pero para el momento no contábamos con un modelo Laravel para nuestra tabla dogs
así que tuvimos que hacer uso de la facade DB
para poder crear nuestro registros.
Un modelo Laravel es importante para nosotros porque es algo más que una forma de interactuar con nuestra base de datos; es una parte fundamental de nuestro ORM Eloquent y nos ayudará a construir relaciones con otros recursos, establecer eventos que se disparan cuando hacemos ciertas acciones y una serie de otras cosas que estaremos aprendiendo en este curso.
Así que, teniendo nuestra base de datos como un lienzo en blanco, arrancaremos esta vez haciendo uso de este importante recurso, cuyo comando de creación es el siguiente:
php artisan make:model Dog
pero como te prometí enseñarte un mejor flujo de trabajo, no sólo una serie de comandos, en lugar del anterior comando, ejecutaremos el siguiente:
php artisan make:model Dog -fm
A diferencia del primer comando, esta vez le hemos pasado los flags -fm
, lo cual creará no solamente el modelo Dog, si no que además se desencadenan una serie de acciones: se creará el archivo DogFactory ubicado en el directorio database/factories
, también creará nuestro archivo migration en su respectivo directorio. Ve y abre este último, agregale el campo "name" y ejecuta la migración.
En este momento tenemos un modelo muy simple en el que nos sumergiremos más en la próxima lección. Por ahora, volvamos a nuestra clase DogsTableSeeder
. En lugar de usar la facade DB
, vamos a recrear esta siembra con el nuevo modelo. Se ve muy similar, pero usamos en su lugar el model factory que acabamos de crear, deberíamos tener algo como esto:
public function run()
{
Dog::factory()->create(['name' => 'Joe']);
Dog::factory()->create(['name' => 'Jock']);
Dog::factory()->create(['name' => 'Jackie']);
Dog::factory()->create(['name' => 'Jane']);
}
fig. 1
Ejecute esto con:
php artisan db:seed –class=DogsTableSeeder
y mira los resultados en la tabla.
Si haz seguido los pasos hasta acá, verás como en la base de datos tienes una tabla llamada dogs
con cuatro registros, pero a diferencia de lo aprendido en el pasado, no hemos configurado la tabla en la que queríamos registrar a nuestro caninos, sin embargo ahí están, ¿como ha sido posible? pues ahora lo veremos.
Una de las ventajas de crear nuestros archivos de la manera que lo hicimos es que, con solo darle un nombre a nuestro modelo y pasarle los flags correspondiente, Laravel toma ese nombre y lo maneja según las convenciones ya establecidas dentro del marco, para de esta manera configurar las relaciones entre cada uno de ellos sin que nosotros tengamos que hacer nada más.
Puedes aprender más sobre como usarlos flags en la creación de modelos en el siguiente enlace: Modelos laravel)
Un ejemplo simple: cuando creamos el modelo llamado Dog, Eloquent asumirá que el nombre de la tabla será "dogs" y su clave principal es "id", por lo que lo configurará de esta manera sin que tengamos que decirle nada, de igual manera procederá a crear los archivos correspondiente a los flags que le enviemos anteponiendo el nombre del modelo, entre otras configuración según el caso (ej. En los model factories verás como agrega el modelo explícitamente como una propiedad de la clase).
Models Factories
Anteriormente habíamos insertado algunos registro mediante nuestro seeder, de una forma muy fácil y agradable si sólo se necesitan unos pocos, sin embargo quedamos con la duda de ¿qué pasa con los momentos en que necesita cargar hasta 100 perros? ¿Puedes pensar en 100 nombres de perros?. Obviamente esto seria una tarea bastante larga y tediosa, y no hablemos de lo mal que queda frente a las buenas prácticas, esto agrandaría nuestro código y estaríamos repitiendo nuestras instrucciones cientos de veces. Podríamos pensar en la implementación de un bucle con la intención de reutilizar nuestra sentencia de creación, esto nos ahorraría muchas lineas de código, sin embargo, no nos quita el problema de los nombres de nuestros amigos caninos, quienes pasarían a llamarse "Qswdcg" o algo por el estilo, por lo que necesitamos una solución que sea más eficiente y consistente, esta solución son los Model factories
.
A partir de la última versión de Laravel (v8.0), la forma de trabajar de las
factories
ha cambiado, así que toma en cuenta que lo que te explicaré acá no será compatible con versiones anteriores, a menos que hagas las respectivas adaptaciones. Si quieres saber mas sobre que cambió puedes revisar el siguiente link: Actualizar model factories.
Los models factories son clases php con la responsabilidad de crear instancias de nuestro objetos con información ya precargada según la configuración que le demos. La verdad son bastante potentes y en esta ultima versión le han sido añadido un gran cantidad de recursos bastante útiles que agilizan y facilitan el desarrollo de nuestras aplicaciones.
Vayamos a nuestro directorio database/factories/
, y encontraremos un archivo llamado DogFactory. Echemos un vistazo:
class DogFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = Dog::class;
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
//
];
}
}
Vemos que nuestra clase solo tiene una propiedad y un método. La propiedad model tiene asignada el modelo con el cual se relaciona, como hemos creado nuestro modelo con el flag correspondiente (-f), esta asignación la hace Laravel por defecto, de no haberla pasado deberíamos hacerlo nosotros manualmente. Con respecto al método definition
, este retorna un array el cual contendrá un par clave-valor, siendo la clave el nombre de nuestros campos asignados en la base de datos, y el valor puede ser lo que queramos que contenga nuestro modelo en dicho atributo cuando creamos una instancia a través de este factory.
public function definition()
{
return [
'name'=> 'Jackie'
];
}
En el ejemplo que acabo de colocar es necesario hacer varias aclaratorias:
Solo he colocado
name
pues es el único campo que hemos agregado en nuestra migración, a pesar de que en nuestra base de datos existen un par de campos más (created_at y updated_at), no es necesarios que los agregue acá puesto que eloquent se encarga de gestionarlos automáticamente.Aunque he añadido una cadena, eso no impedirá que cuando ejecute el seeder, los nombres que yo haya asignado cuando creo una instancia de Dog mediante factory (ver fig. 1) sean asignado.
(ej. Puedo ejecutar Dog::factory()->create(['name' => 'Jock']); y el registro se guardará como Jock y no como Jackie, pues estoy sobrescribiendo la configuración dada.Si! seguimos teniendo el problema de crear muchos registros, puesto que todos se llamarán Jackie, pero no te apresures, fue intencional por motivos ilustrativos.
¿Como podemos hacer entonces para que nuestros amigos tengan todos nombres distintos? Pues aquí entra el segundo elemento de nuestra lista Faker, recurso bastante interesante que nos ayudará a poblar nuestra base de datos de una manera consistente y dinámica.
Faker
Faker es una biblioteca maravillosa que nos dará datos falsos pero realistas que podremos sembrar.
Hagamos una fábrica para perros y luego veamos cómo usarla en nuestro seeder:
public function definition()
{
return [
'name'=> $this->faker->firstName
];
}
y ahora en nuestro seeder:
public function run()
{
Dog::factory()->count(10)->create();
}
Acá le estamos indicando a nuestro seeder que pueble nuestra base de datos con 10 registros, por lo que procederá a registrar 10 perros en nuestra tabla dogs
, verás como cada uno tiene su propio nombre, y además ese nombre es perfectamente legible y pronunciable (si, se que siguen siendo algunos nombre raros para unos perros...bueno todos, pero es mejor que llamarlos “Jsdhak”).
Puedes migrar y sembrar las veces que quieras (recuerda las buenas prácticas que hemos aprendido) y jugar con la cantidad de registros, notarás como siempre los nombres son distintos para cada uno de tus caninos.
Hay un último consejo que aprender antes de terminar por hoy que nos ahorrará tener que recordar y escribir todo ese comando cuando sembramos nuestros registros de perros. Hasta ahora siempre hemos ejecutado nuestro comando sembrador pasando el nombre del seeder a ejecutar, esto lo podemos cambiar si hacemos una pequeña configuración que nos facilitará aun más las cosas.
Vamos al directorio database/seeds/
y abrimos el archivo DatabaseSeeder.php
, esta es de alguna forma una clase madre en la que podemos llamar de manera individual todos y cada uno de nuestro seeders, por ahora solo tenemos uno, pero cuando nos toque trabajar con aplicaciones más grandes, agradeceremos por la existencia de este gran elemento.
Como ya hemos abierto el archivo, procedamos entonces a agregar nuestro DogSeeder
para que su clase madre, al ser llamada, ejecute todo lo que en ella este contenida:
public function run()
{
$this->call(DogsTableSeeder::class);
}
El método run debe verse como en el código anterior, con esto ya hemos añadido nuestro seeder, de ahora en adelante, cada vez que queramos que nuestros seeders se ejecuten por lote, los agregaremos acá,y eso será todo, podremos recrear toda nuestra base de datos con datos de semillas con un comando simple:
php artisan migrate:refresh --seed
Hasta ahora llevamos dos lección y todavía apenas hemos tocado Eloquent!. No te preocupes que eso va a cambiar a partir de la próxima entrega, pero era necesario aprender lo que hasta ahora hemos visto, pues nos facilitará enormemente la vida ayudándonos a crear un entorno de desarrollo de forma rápida y sencilla ahorrándonos mucho tiempo y frustración a medida que creamos nuestro proyecto.
Puedes ampliar mucho mas revisando la documentación oficial de Laravel, te invito a que de verdad le des una ojeada, pues facilitará mucho tu curva de aprendizaje.
Quédate atento a la próxima entrega, si tienes alguna duda puedes contactarme en mi cuenta de Twitter @johantovar o déjala en los comentarios. Hasta entonces y que tengas un feliz y exitoso día.
Posted on April 19, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.