Newsletter para devsEntra

Laravel series III: Bases de datos + modelo

laravel_bases_de_datos_y_modelo

Como siempre, para empezar, por aquí os dejo el índice de esta series sobre el framework de PHP, Laravel:

Hoy, el tema que nos atañe es la persistencia de datos; uno de los temas que a los desarrolladores más nos suele atraer y a la par, el que más quebraderos de cabeza nos suele ocasionar.

Laravel viene a ayudarnos con el ORM Eloquent.

Aunque supongo que lo primero que os preguntaréis es ¿qué es un ORM?.

Un ORM, mapeado de objetos relacional (Object Relational Mapping en inglés), se encarga de tener un espejo de nuestra base de datos en nuestro código a base de objetos.

Si lo interpretamos de una manera más simple podemos decir que las tablas de nuestra base de datos tienen su equivalente como objeto dentro de nuestro código.

Si a esto le añadimos un sistema de consultas a base de datos (Query builder en Laravel), se nos permitirá hacer consultas a la base de datos de una manera más fácil.

Bases de datos

De manera nativa, Laravel integra compatibilidad con cuatro tipos de base de datos en su versión 8:

  • MySQL 5.7+
  • PostgreSQL 9.6+
  • SQLite 3.8.8+
  • SQL Server 2017+

Como buen ‘PHPero’, el ejemplo de configuración que os voy a dar es con MySQL.

Os quedaréis asombrados con lo fácil que es configurar una base de datos en Laravel.

El archivo principal que contiene la configuración a la base de datos es config/database.php.

Dentro, podréis encontrar, en formato JSON, todos los parámetros de configuración para los distintos tipos de bases de datos que se han enumerado anteriormente.

OS pego la parte del código que hace referencia a SQLite y MySQL:

<?php

use Illuminate\Support\Str;

return [

    'default' => env('DB_CONNECTION', 'mysql'),

    'connections' => [

        'sqlite' => [
            'driver' => 'sqlite',
            'url' => env('DATABASE_URL'),
            'database' => env('DB_DATABASE', database_path('database.sqlite')),
            'prefix' => '',
            'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
        ],

        'mysql' => [
            'driver' => 'mysql',
            'url' => env('DATABASE_URL'),
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'prefix_indexes' => true,
            'strict' => true,
            'engine' => null,
            'options' => extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
            ]) : [],
        ],
            
 ...

Pero ahora os estaréis preguntando:

Juanjo, ¿dónde pongo los valores?. Solo veo algunos en los que se pueden introducir o que tienen valores por defecto. Pero ¿y el resto?

Si os fijáis un poco, al comienzo de cada valor de parámetro tenemos una función: env().

Esta función hace referencia a las variables de entorno del sistema operativo.

Almacenar los valores de los parámetros en las variables de entorno del sistema operativo del servidor es una práctica que se viene haciendo desde hace un tiempo y que evita que valores sensibles (como contraseñas), estén insertados dentro del código directamente.

Además, las variables de entorno sirven como punto común de almacenamiento de valores, lo cual evita que estos valores estén en varios puntos dentro de nuestro código. Sólo cambiamos su valor en un archivo.

Por otro lado, como práctica habitual, este archivo de valores de variables de entorno no se sube a nuestro repositorio de GIT (Laravel incluye este archivo en .gitignore por defecto), lo que hace que valores sensibles no estén expuestos al exterior.

El archivo que contiene las variables de entorno se suele encontrar en el raíz del sitio, en un archivo llamado .env.

Aquí podéis ver un ejemplo del contenido del archivo:

APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:D2ie5234JDiwegbk+jasd01Qq34qHCL1QfE0hurh8=
APP_DEBUG=true
APP_URL=http://localhost

LOG_CHANNEL=stack
LOG_LEVEL=debug

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=db_name
DB_USERNAME=db_user
DB_PASSWORD=XXXXXXXXX

Cómo podéis ver, Laravel se apoya en este archivo no sólo para contener los parámetros de la base de datos, sino también para configuraciones propias de la aplicación, como la URL de la misma, nombre, si la aplicación se encuentra en modo depuración, etc.

Toda la configuración de la base de datos está contenida dentro del bloque que comienza por DB_, y aquí es donde especificamos el tipo de base de datos a utilizar.

El parámetro DB_CONNNECTION hace referencia a las distintas declaraciones que vimos en el archivo config/database.php anterior.

Si quisiéramos utilizar SQLite, DB_CONNECTION contendría el valor sqlite.

Como seguro habréis deducido ya, los parámetros de conexión deben de hacer referencia al servidor MySQL configurado en el equipo servidor.

En mi caso normalmente instalo MariaDB, un fork de Mysql que se puede descargar desde la web oficial de MariaDB.

Gestión de tablas. El modelo.

Tal y como explicamos en la introducción, los ORM tienen la capacidad de generar un espejo de la base de datos en nuestro código de modo que podamos utilizar clases como si fueran las tablas de nuestra base de datos.

Estas clases, tanto en Eloquent como en cualquier otro ORM, son denominadas modelos.

Vamos a quedarnos con este concepto, cada tabla de la base de datos tiene su correspondiente modelo en código que es usado para interactuar con la misma. Y no sólo se interactúa haciendo consultas de datos, sino que también tendremos la capacidad de insertar, modificar y borrar registros en la tabla correspondiente.

La carpeta por defecto donde viven los modelos en Laravel es app\Models.

Para generar un nuevo modelo, podemos utilizar la consola de comandos de Laravel (ya la vimos en el artículo anterior) de la siguiente forma:

php artisan make:model Product

En este caso hemos creado un modelo denominado Product.

Este comando genera el siguiente código en la carpeta antes indicada:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    //
}

Fijaos como la clase declarada extiende otra clase, la clase Model, de la cual Product hereda propiedades y métodos.

Este tipo de herencias automáticas son las que crean toda la magia en Laravel.

Con crear el modelo, tal y como lo hemos hecho, y teniendo la clase Product ubicada donde está, el sistema asume que tenemos una tabla products en la base de datos configurada en el punto que vimos anteriormente.

Supongo que que ya os habéis dado cuenta…

¿Porqué el modelo se llama Product y la tabla en la base de datos se llama products?

Y aquí es donde encajamos algo que tenemos que tener en cuenta: si nos amoldamos a programar de una forma tan automática, con tanta magia, tenemos que seguir las reglas del ORM.

En este caso Eloquent espera que declares los modelos en singular y que la tabla en la base de datos tenga el mismo nombre pero en plural (todo en minúsculas como habrás podido comprobar).

Además Eloquent sigue la convención ‘snake case’, lo que quiere decir que si declaramos un modelo llamado así: ProductsBoughtByClient la base de datos debe contener una tabla products_bought_by_clients.

Notad como Eloquent espera un nombre de tabla que esté en ‘camel case’ (convención por defecto de PHP), lo transforma a ‘snake case’ (convención por defecto en bases de datos) y añade una ‘s’ al final

Pero Eloquent no es tan cabezón como cabe esperar, no obliga a tener que llamar a las tablas de una manera concreta, esto es sólo si no queremos andar especificando nombre de tablas.

Si quisiéramos llamar a la tabla de una forma concreta, basta con especificarlo como propiedad dentro del modelo:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    /**
    * Table associated with the model.
    *
    */
    protected $table = 'my_products';
}

En este caso, el nombre de la tabla de productos en la base de datos que corresponde a este modelo se llama my_products.

Tened en cuenta que hemos tenido que crear la tabla a mano en la base de datos para que Eloquent tenga capacidad de conectarse a la misma, pero esto no siempre es así.

Eloquent tiene la capacidad de crear la tabla e incluso alimentarla con registros de prueba. Esto se hace mediante migraciones y seeders.

Pero no os quiero abrumar mucho más en este artículo, eso lo veremos en el siguiente.

Por ahora sólo quiero mostraros cómo podemos realizar una consulta a la base de datos a través del constructor de consultas (query builder).

Así que vamos a obtener todos los registros de la tabla products que tengan el campo deleted con valor cero y además ordenarlos por nombre.

$products = Product::where('deleted',0)
            ->orderBy('name')
            ->get();

Fácil de leer, ¿verdad?

Esta línea de código devuelve un objeto que tiene como propiedades las columnas de la tabla y que contiene los registros de la misma.

Obtener el nombre del producto será tan fácil como: $products->name.

¿Te has quedado con ganas?

En el siguiente artículo veremos cómo implementar todo lo que hemos aprendido hoy, así que no penséis que aquí queda todo.

Nos esperan:

  • Migraciones.
  • Seeders.
  • Consultas, modificaciones y eliminación de registros.
  • Todo esto en una pequeña aplicación que subiré a GitHub.

Aún así, si no podéis esperar, o queréis ampliar conocimientos, os recomiendo que os paséis por una sesión básica de Laravel que Daniel Primo preparó en directo para todos los integrantes de su zona premium: Introducción a Laravel.

¡Nos vemos en el siguiente fragmento de código!

Escrito originalmente por: Juan José Ramos

Imagen de Daniel Primo

Daniel Primo

CEO en pantuflas de Web Reactiva. Programador y formador en tecnologías que cambian el mundo y a las personas. Activo en linkedin, en substack y canal @webreactiva en telegram

12 recursos para developers cada domingo en tu bandeja de entrada

Además de una skill práctica bien explicada, trucos para mejorar tu futuro profesional y una pizquita de humor útil para el resto de la semana. Gratis.