Publi

Utilizando Eloquent para interactuar con bases de datos en nuestros proyectos paso a paso.

Eloquent para bases de datos
Parece que fue ayer cuando, cada vez que necesitamos hacer algo con bases de datos en algún proyecto, abríamos la conexión y hacíamos la consulta a mano… mysql_connect(), mysql_query(), mysql_fetch_assoc()… No está mal cuando queremos aprender cómo funciona todo, pero cuando vamos a ponernos a programar en el mundo real, nos viene mejor programar con sistemas que nos hagan la vida un poco más fácil y nos separen en cierto modo de las consultas que hacemos a la base de datos. La principal ventaja de esto es que podemos hacer que nuestro sistema no dependa de un motor específico de base de datos, abriendo la posibilidad de poder cambiar el día de mañana a otro motor sin demasiado esfuerzo; y que, al escribir código SQL nos podemos equivocar, incluso hacer llamadas inseguras. En estos casos un sistema ORM nos abstraerá de todo eso y hará que nosotros vayamos al grano, al tratamiento y la utilización de los datos.

En PHP, uno de los ORM más famosos y con más usuarios actualmente es Eloquent, perteneciente al framework Laravel. Aunque, una de las grandes ventajas que encontramos, es que no tenemos por qué utilizar Laravel en nuestro proyecto para utilizar Eloquent. Así que, vamos a empezar un pequeño proyecto utilizando Eloquent, a pelo, para descubrir qué podemos hacer con él e incorporarlo a nuestros proyectos cuanto antes.

En esta guía no quiero profundizar demasiado en conceptos propios de un framework, para que nuestro código pueda ser incorporado en cualquier lado de forma más o menos fácil. Además, he intentado simplificar al máximo las cosas para que todo quede claro. Por supuesto, todo se puede complicar hasta la saciedad y más allá.

Instalación con composer

Como en todo PHP moderno, vamos a utilizar composer para incorporar Eloquent en nuestro proyecto. Con composer, además, vamos a poder tener el módulo actualizado en todo momento. Es cierto que, incorporar nuevos módulos a nuestros proyectos puede ser peligroso, pero Eloquent, tiene toda la pinta de ser de confianza. En total, con dependencias y todo son cerca de 4Mb de espacio (a febrero de 2018).

composer require illuminate/database

Ahora, crearemos un directorio para nuestros modelos, por ejemplo app/Models donde ubicaremos los modelos con los que vamos a trabajar (en este ejemplo sólo hay un modelo, pero de esta forma general podremos quitarnos muchos includes del medio y nos puede servir para proyectos más grandes):

mkdir -p app/Models

Y editamos el archivo composer.json (que seguro que ha creado composer) para que se carguen automáticamente los archivos de estos directorios. Dejándolo más o menos así:
1
2
3
4
5
6
7
8
{
    "require": {
        "illuminate/database": "^5.6"
    },
    "autoload": {
        "psr-4": {"App\": "app/"}
    }
}

Tras ello,

composer update

Ya tenemos una estructura de nuestro pequeño proyecto más o menos lista para funcionar. Ahora, trabajaremos en varios archivos php donde iremos demostrando algunas capacidades de nuestro ORM. Para nuestros ejemplos, vamos a hacer consultas sobre una tabla de usuarios con nombre de usuario, e-mail, password y fechas de acceso y creación.

Configuración y bootstrap

Primero vamos a crear el archivo de configuración. En mi caso, la base de datos será MySQL, así que voy a configurar el sistema para mi base de datos. Atención, estoy en local, el password de mi base de datos no es de otro mundo. Aunque es importante que los nombres de las claves del array se mantengan, ya que se lo pasaremos directamente al gestor de base de datos (config.php).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
/* Podemos crear esto de muchas formas, pero para un ejemplo
 vamos a tirar de una variable de tipo array con toda la configuración.
*/

$config = array(
    'database' => array(
            'driver' => 'mysql',
            'host' => '192.168.0.7',
            'port' => '5167',
            'database' => 'EloquentPoetry',
            'username' => 'eloqpoet',
            'password' => 'teopqole',
            'charset' => 'utf8',
            'collation' => 'utf8_unicode_ci',
    )
);

Creando el modelo

Vamos a crear algunos elementos, como una tabla en base de datos. Nuestra tabla de usuarios. Para ello, en MySQL o MariaDB insertamos esto:

1
2
3
4
5
6
7
8
9
10
11
12
DROP TABLE Users;
CREATE TABLE IF NOT EXISTS Users (
  `User_id` BIGINT(20) NOT NULL AUTO_INCREMENT,
  `Username` VARCHAR(128) NOT NULL,
    `Email` VARCHAR(255) NOT NULL,
  `Password` VARCHAR(128) NOT NULL,
  `Created_at` DATETIME NOT NULL,
    `Updated_at` DATETIME NOT NULL,
  `Accessed` DATETIME,
  PRIMARY KEY (`User_id`),
  UNIQUE `Username` (`Username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Y ahora, creamos el archivo app/Models/User.php, sólo crearemos la clase para acceder a la tabla (por ahora):

1
2
3
4
5
6
7
8
<?php
namespace App\Models;

class User extends \Illuminate\Database\Eloquent\Model {
    protected $table = 'Users';
    protected $primaryKey = 'User_id';

}

Vemos que en el modelo podemos especificar el nombre de la tabla vinculada y el nombre del campo que será clave primaria (por defecto será id). Podremos especificar más cosas, pero por ahora, con esto nos vale.

Archivo principal

Nuestro archivo principal, que por ahora será users.php en el directorio base de nuestro proyecto, se encargará de insertar un registro de usuario, y listar todo lo que hay en la tabla:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
/* Incluimos los ficheros necesarios */
require 'vendor/autoload.php';
require 'app/config.php';

/* Iniciamos el sistema de base de datos */
$capsule = new \Illuminate\Database\Capsule\Manager;
$capsule->addConnection($config['database']);
$capsule->setAsGlobal();
$capsule->bootEloquent();

/* Creamos un elemento en la tabla */
$user = new App\Models\User();
$user->username="gaspar";
$user->email="gaspy@totaki.com";
$user->password=md5('rapsag');
$user->accessed=NULL;

/* Listamos los elementos de la tabla */
$all = App\Models\User::all();
if (count($all)) {
    foreach ($all as $user) {
        echo "Nombre de usuario: ".$user->Username."\n";
        echo "Email: ".$user->Email."\n";
        echo "Registrado: ".$user->Created_at."\n";
        echo "Último acceso: ".(($user->Accessed)??"Nunca")."\n";
        echo "------------------\n\n";
    }
} else {
    echo "No hay nada en la tabla\n";
}

Vale, estamos complicándolo todo mucho, el archivo principal debe quedar mucho más reducido. No debemos preocuparnos de cómo se almacenan los datos ni nada, y el hecho de insertar algo en base de datos es algo que no deberíamos ver en el fichero principal. Podemos implementarlo en el mismo modelo.

Un lenguaje más natural

Llegados a este punto, dentro del modelo, podremos implementar todos aquellos métodos que consideremos necesarios para que este funcione como un ente independiente y podamos hablar con él con naturalidad. Por ejemplo, un método para crear un usuario que devuelva el id de usuario, una consulta sobre los privilegios o los elementos a los que puede acceder, etc. Aunque Eloquent incorpora muchas facilidades, este post es más que nada introductorio, así que vamos a crear un método para crear un usuario:

1
2
3
4
5
6
7
8
9
10
11
12
13
    public static function nuevo($nombre, $password, $email) {
        try {
            $nuser = new self;
            $nuser->username = $nombre;
            $nuser->password = md5($password);
            $nuser->email = $email;
            $nuser->accessed = null;
            return ($nuser->save())?$nuser->{$nuser->primaryKey}:false;
        } catch (\Exception $e) {
            var_dump($e);
            return null;
        }
    }

Y en el programa principal, para crear el usuario sólo haríamos:

1
2
3
4
5
$userId = App\Models\User::nuevo('gaspar', 'rapsag', 'gaspy@totaki.com');
if ($userId)
    echo "Nuevo usuario con ID: ".$userId."\n";
else
    echo "No se pudo insertar usuario\n";

Alternativamente, este comportamiento podríamos hacerlo de forma parecida, utilizando las propias características de modelos de Eloquent. Aunque para el almacenamiento de la contraseña con md5() (niños, no hagáis esto en casa), necesitaremos el gestor de eventos de Laravel, que lo podemos incluir en nuestro proyecto con:

composer install illuminate/events

Este gestor no es demasiado grande y podrá darnos funcionalidades muy interesantes en nuestros proyectos. Ahora, el modelo quedaría así:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
namespace App\Models;

class User extends \Illuminate\Database\Eloquent\Model {
    protected $table = 'Users';
    protected $primaryKey = 'User_id';
    protected $fillable = array('username', 'password', 'email');

    protected static function boot()
    {
        parent::boot();
        static::setEventDispatcher(new \Illuminate\Events\Dispatcher());

        static::creating(function ($model) {
            $model->password = md5($model->password);
        });
        static::updating(function ($model) {
            $model->password = md5($model->password);
        });

    }
}

En el modelo, ahora definimos en la variable fillable los campos de base de datos que podremos rellenar desde fuera. Y en el método boot() incluiremos funciones que se dispararán en el evento de creación y actualización del modelo. Es decir, nosotros le metemos al modelo la clave en texto plano y éste la almacenará en cifrada en base de datos.
El programa principal, en la parte de inserción del usuario quedaría así:

1
2
3
4
5
6
7
/* Creamos un elemento en la tabla */
if ($user = App\Models\User::create(array('username' => 'gaspar',
                                          'password' => 'rapsag',
                                          'email' => 'gaspy@totaki.com')))
    echo "Nuevo usuario con ID: ".$user->User_id."\n";
else
    echo "No se pudo insertar usuario\n";

Más información

Ya que este post es introductorio no quería alargarme demasiado, ni explicar cómo funciona Eloquent. Si quieres más información sobre el funcionamiento de Eloquent, puedes mirar la documentación, que tiene muchísimos ejemplos y mucho detalle de cómo hacerlo todo.

Foto principal: unsplash-logoKane Reinholdtsen

También podría interesarte....

Leave a Reply