Los primeros modelos

Cada persona agrega una pieza al modelo de datos del videoclub

Marco González Luengo

Tabla de contenidos
  1. 1. Clonar el proyecto del grupo
  2. 2. Leer lo que ya existe
  3. 3. Tu rama
  4. 4. Tu modelo
  5. Copia
  6. Clasificacion
  7. Socio
  8. 5. Los pasos, uno por uno
  9. Generar los archivos
  10. La migración
  11. El modelo
  12. El seeder
  13. Probar desde cero
  14. 6. Subirlo
  15. 7. La revisión
  16. Cuando esté todo fusionado

Hasta ahora Blockbuster tiene un catálogo: géneros y películas. Con eso todavía no se puede arrendar nada. Faltan las copias que están en la estantería, las personas que se las llevan y las reglas sobre quién puede ver qué.

Cada integrante del equipo va a agregar una de esas piezas, completa, y a subirla para que el resto la tenga.

1. Clonar el proyecto del grupo

El repositorio es prv-cftohiggins/blockbuster. Clónalo en una carpeta nueva, blockbuster-grupo:

cd ~/Proyectos
git clone git@github.com:prv-cftohiggins/blockbuster.git blockbuster-grupo
cd blockbuster-grupo

Y hazlo funcionar, igual que en Clonar, cambiar y subir:

lerd setup
php artisan migrate:fresh --seed

migrate:fresh --seed borra las tablas, las crea de nuevo y carga los datos de prueba. Abre http://blockbuster-grupo.test/peliculas: deberías ver el catálogo.

Ábrelo también en PhpStorm. El README.md del proyecto tiene estas mismas instrucciones, para cuando las necesites de nuevo.

2. Leer lo que ya existe

Antes de escribir, mira cómo está hecho lo que hay. Tu modelo va a seguir el mismo patrón. Una película son cuatro archivos:

Archivo Qué hace
database/migrations/..._create_peliculas_table.php Define las columnas de la tabla
app/Models/Pelicula.php La clase: qué se puede llenar y con qué se relaciona
database/seeders/PeliculaSeeder.php Los datos de prueba
database/seeders/DatabaseSeeder.php La lista de seeders, en orden

Fíjate en tres cosas de Pelicula.php:

Y pruébalo en vivo. Tinker es una consola para hablar con tus modelos:

php artisan tinker
App\Models\Pelicula::count();
App\Models\Pelicula::where('anio', '<', 1990)->pluck('titulo');
App\Models\Pelicula::first()->genero->nombre;
App\Models\Genero::where('nombre', 'Terror')->first()->peliculas;

Se sale con exit.

3. Tu rama

Tres personas escribiendo sobre main al mismo tiempo se pisan. Cada una trabaja en una rama: una línea de trabajo propia, que después se junta con la principal.

git switch -c copia

git switch -c crea la rama y te cambia a ella. Ponle el nombre de tu modelo: copia, clasificacion o socio. Desde PhpStorm es Git → New Branch.

4. Tu modelo

Hay tres. Los tres se construyen con los mismos pasos, que están más abajo; lo que cambia es la tabla y un detalle propio de cada uno.

Copia

Lo que se arrienda no es la película: es una copia física de la película. Puede haber cinco copias de Matrix, y cada una está disponible o no.

Tabla copias:

Columna Tipo Notas
pelicula_id llave foránea A qué película corresponde
codigo string, único El código de la etiqueta: BB-0001, BB-0002…
formato string VHS, DVD o Blu-ray
estado string disponible, arrendada, danada o baja. Por defecto, disponible

Para comprobar, en Tinker:

App\Models\Pelicula::first()->copias;
App\Models\Copia::first()->pelicula->titulo;
App\Models\Copia::where('estado', 'disponible')->count();
App\Models\Copia::first()->estaDisponible();

Clasificacion

No todas las películas son para todas las edades. En Chile las califica el Consejo de Calificación Cinematográfica, con cuatro categorías.

Tabla clasificaciones:

Columna Tipo Notas
codigo string, único TE, TE+7, 14 o 18
nombre string «Todo espectador», «Mayores de 14 años»…
edad_minima integer 0, 7, 14 o 18

Y una columna nueva en la tabla peliculas, en una segunda migración:

Columna Tipo Notas
clasificacion_id llave foránea, puede ser nula Las películas que ya existen no tienen clasificación todavía

Para comprobar, en Tinker:

App\Models\Clasificacion::count();
App\Models\Pelicula::where('titulo', 'Toy Story')->first()->clasificacion->codigo;
App\Models\Clasificacion::where('codigo', '18')->first()->peliculas->pluck('titulo');
App\Models\Clasificacion::where('codigo', '14')->first()->permite(12);

Socio

Para arrendar hay que ser socio del videoclub. De cada socio interesa saber quién es, cómo ubicarlo y si está al día.

Tabla socios:

Columna Tipo Notas
rut string, único Con guion y dígito verificador: 12345678-5
nombre string
email string, único
telefono string, puede ser nulo
fecha_nacimiento date
estado string activo o suspendido. Por defecto, activo

Para comprobar, en Tinker:

App\Models\Socio::count();
App\Models\Socio::first()->edad();
App\Models\Socio::where('estado', 'suspendido')->first()->estaActivo();
App\Models\Socio::create(['rut' => App\Models\Socio::first()->rut, 'nombre' => 'Repetido', 'email' => 'otro@example.com', 'fecha_nacimiento' => '2000-01-01']);

La última línea tiene que fallar: no puede haber dos socios con el mismo RUT.

5. Los pasos, uno por uno

Los ejemplos usan Copia. Cambia el nombre por el de tu modelo.

Generar los archivos

php artisan make:model Copia --migration --seed

Crea el modelo, su migración y su seeder, vacíos.

La migración

En el método up() de la migración nueva van las columnas. Mira la de peliculas como guía, y la lista de tipos de columna. Algunas que vas a necesitar:

$table->foreignId('pelicula_id')->constrained();   // llave foránea a peliculas
$table->string('codigo')->unique();                // no se puede repetir
$table->string('estado')->default('disponible');   // valor si no se indica otro
$table->string('telefono')->nullable();            // puede quedar vacío
$table->date('fecha_nacimiento');
$table->softDeletes();                             // la columna deleted_at

Para agregar una columna a una tabla que ya existe se crea otra migración:

php artisan make:migration add_clasificacion_id_to_peliculas_table

Y adentro se usa Schema::table('peliculas', ...) en vez de Schema::create. La migración ..._ajusta_generos_y_peliculas.php del proyecto es un ejemplo.

Ejecuta lo nuevo:

php artisan migrate

Si te equivocaste en una columna, php artisan migrate:rollback deshace la última tanda. Corrige el archivo y vuelve a migrar.

El modelo

Sigue a Pelicula.php: use SoftDeletes, el $fillable con tus columnas, tus relaciones y tu método propio.

public function pelicula(): BelongsTo
{
    return $this->belongsTo(Pelicula::class);
}

public function estaDisponible(): bool
{
    return $this->estado === 'disponible';
}

No escribas los use de arriba a mano: Alt+Enter sobre BelongsTo lo importa.

Si tu modelo se relaciona con otro, agrega la relación inversa en el otro modelo. Para Copia, en Pelicula.php:

public function copias(): HasMany
{
    return $this->hasMany(Copia::class);
}

El seeder

Los datos de prueba van en el método run() de tu seeder. Usa updateOrCreate, como PeliculaSeeder: el primer array es cómo reconocer la fila, el segundo es el resto de los datos. Así se puede ejecutar varias veces sin duplicar nada.

Copia::updateOrCreate(
    ['codigo' => 'BB-0001'],
    ['pelicula_id' => $pelicula->id, 'formato' => 'VHS'],
);

Después regístralo en DatabaseSeeder.php, al final de la lista. El orden importa: si tu seeder necesita películas, va después de PeliculaSeeder.

Probar desde cero

php artisan migrate:fresh --seed

Si esto termina sin errores y las consultas de Tinker de tu modelo responden lo esperado, está listo.

6. Subirlo

Revisa qué cambiaste, y guarda:

git status
git add .
git commit -m "Modelo Copia con migración y seeder"
git push -u origin copia

El -u origin copia solo hace falta la primera vez: crea la rama en GitHub y la deja enlazada con la tuya.

Ahora entra al repositorio en GitHub. Va a aparecer un aviso con el botón Compare & pull request. Un pull request es pedirle al equipo que revise tu rama y la sume a main. Escribe en la descripción qué agregaste y cómo probarlo, y créalo. Con eso tu parte está entregada: lo que sigue es la revisión.

7. La revisión

Nadie fusiona su propio pull request. Lo revisa la PM del proyecto, que es quien decide qué entra a main. Pueden pasar dos cosas:

Mientras esperas, mira el trabajo del resto. Leer código ajeno es la mitad del oficio:

  1. En GitHub, abre otro pull request y lee los cambios en la pestaña Files changed.

  2. Si quieres probarlo en tu computador:

    git fetch
    git switch clasificacion
    php artisan migrate:fresh --seed
    
  3. Corre las consultas de Tinker de ese modelo. Si algo falla o no se entiende, déjalo como comentario en el pull request, con el mensaje de error completo.

Para volver a tu trabajo: git switch copia.

Cuando esté todo fusionado

Vuelve a main, trae lo de todos y reconstruye:

git switch main
git pull
composer install
php artisan migrate:fresh --seed

Ahora tu Blockbuster tiene películas con clasificación, copias en la estantería y socios. Falta lo que los une: el arriendo, que junta a un socio con una copia y tiene que revisar que la copia esté disponible, que el socio esté activo y que tenga edad para verla. Las tres piezas que acaban de construir son justo las que necesita.