Eloquent, nuestro ORM favorito

Eloquent, nuestro ORM favorito

En Servitux usamos Laravel para el desarrollo de las plataformas web de nuestros clientes. Uno de los pilares fundamentales de Laravel es su ORM, Eloquent, el cual nos permite interactuar con la base de datos de manera bastante potente. Conocer su funcionamiento profundamente puede ayudarnos a construir soluciones más robustas, basadas en standard de programación que nos permitan escalar el software mucho más fácilmente.

A continuación os proponemos una serie de «trucos» que a nosotros nos funcionan de maravilla. ¡Espero que os sirvan de mucho en vuestros desarrollos!

Trabajo con Tablas

Renombrar una tabla:

Schema::rename($previousName, $newName);

Borrar una tabla:

Schema::drop($tableName);
Schema::dropIfExists($tableName);

Comprobar si una tabla Existe:

if (Schema::hasTable('books'))
{
//la tabla 'books' existe
}

Comprobar si un campo existe:

if (Schema::hasColumn('books', 'title'))
{
// the column "title" in the "books" table exists...
}

Cambiar el tamaño de un campo:

$table->string('title', 250)->change();

Añadir el «Borrado suave» a tu tabla:

$table->softDeletes();

Los softDeletes son una herramienta muy potente para marcar registros como borrados, pero no borrarlos realmente. Este método añade el campo «deleted_at» a tu tabla, además de un Scope (que analizaremos más adelante) para evitar leer esos registros en todas tus consultas. De esa manera, eliminas esos resultados en la presentación de tus datos al usuario. La llamada a «delete» no lo elimina, si no que rellena el timestamp con la fecha/hora del borrado.

$model->delete();

Evidentemente, hay una forma de tenerlos en cuenta, si añadimos «withTrashed» a nuestra consulta:

\App\Book::withTrashed()->find($id);

Además, podemos restaurar una baja, mediante el método «restore«;

$model = \App\Book::withTrashed()->find($id);
$model->restore();

O eliminar completamente el registro:

$model->forceDelete();

Para poder utilizar todos estos métodos, tendréis que modificar vuestros modelos para usar los soft deletes:

use SoftDeletes;
protected $dates = ['deleted_at'];

Añadir índices a tu Tabla (además del primary, que todos conocemos…):

$table->unique('email');
$table->index('title');
$table->foreign('author_id')->references('id')->on('authors');

Los foreign index son importantes, ya que nos permiten las actualizaciones en cascada:

$table->foreign('author_id')->references('id')->on('authors')->onDelete('cascade');

Además, nos permiten utilizar una serie de métodos en nuestro modelos que veremos más adelante.

Trabajo con Consultas

Si has trabajado con Eloquent alguna vez, y tienes conocimientos básicos de SQL, sabrás todo lo que se puede hacer con las Querys de ORM. A continuación, vamos a omitir los clásicos «where» y te mostraremos algún truquito que te puede venir bien según el caso:

Where’s Especiales:

Obtener resultados entre dos valores de campo (También para fechas!):

$results = \App\Book::whereBetween('pages_count', [100, 200])->get();

Obtener resultados en base a una colección de valores:

$results = \App\Book::whereIn('title', ['My First Book!','My Second Book!'])->get();

Obtener resultados en base a valores null:

$results = \App\Book::whereNull('title')->get();

Trabajo con Magic Querys:

Una característica bastante curiosa de Eloquent son la posibilidad de realizar llamadas a métodos que resumen una Query más compleja. Os pongo un ejemplo simple. Podéis hacer lo siguiente:

$result = \App\Book::where('pages_count', '=', 1000);

O realizar la siguiente Magic Query:

$result = \App\Book::wherePagesCount(1000);

Eloquent reconocerá la existencia del campo que escribís tras el «where» y «traducirá» la Query tal y como la hemos escrito más arriba, obteniendo el mismo resultado. Como dicen ellos mismos: Mágia!

Query Scopes

Una de las características que, personalmente, más me gustan de Eloquent, son las Query Scopes, las cuales te dan la posibilidad de añadir restricciones automáticas a tus consultas, ya sea a nivel local o a nivel global. Especialmente útiles para cuando compartís base de datos entre distintos clientes, y no queréis que se vean entre ellos!.

Query Scopes Locales

Podemos definir todas las Query Scopes que queramos en un modelo concreto, de la siguiente forma:

public function scopeCheap($query)
{
   return $query->where('price', '<', 10);
}

public function scopeLong($query)
{
   return $query->where('pages_count', '>', 700);
}

Y luego acceder a ellas realizando una simple query:

$results = $model->long()->get();

e incluso encadenarlas:

$results = $model->long()->cheap()->get();

Global Query Scopes

Un Query Scope puede definirse a nivel global, y luego indicar en que modelos queremos usarlo. Volviendo al ejemplo de una base de datos compartida para varios clientes, imaginad que cada usuario de nuestro proyecto (\App\User) tiene un cliente asignado, definido por su compo «id_customer». De esa manera, podríamos definir un Global Scope de este tipo:

<?php

namespace App\Scopes;

use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

use Illuminate\Support\Facades\Auth;

class CustomerScope implements Scope
{
   public function apply(Builder $builder, Model $model)
   {
      $builder->where('id_customer', Auth::user()->id_customer);
   }
}

Y luego aplicarselo a nuestros modelos de la siguiente forma:

use App\Scopes\CustomerScope;

class Data extends Model
{
   protected static function boot()
   {
      parent::boot();

      static::addGlobalScope(new CustomerScope);
   }
}

Hemos dado un pequeño repaso por alguno de las características más desconocidas de Eloquent. Si queréis amplicar información sobre el tema, siempre podéis tirar de la documentación oficial de Laravel.

Desde Servitux siempre intentamos implementar las mejores soluciones para cada cliente, y entender bien como funciona el framework con el que trabajamos, ayuda a la implementación y mantenimiento del cualquier proyecto. Un consejo importante es intentar mantener siempre la estandarización del desarrollo, mediante el cual, podréis ir escalando vuestro proyecto de una manera muy flexible, pudiendo añadir las nuevas características que vayan saliendo en tu framework con el mínimo esfuerzo.

Os invito a pasaros por nuestra sección de desarrollo y echar un vistazo a nuestra sección de Plataformas Web, donde podréis ver algunos de los proyectos que hemos desarrollado ya. Quizá eso os de el empujoncito que necesitáis para llamarnos y trabajar juntos!

Juan Carlos Ferrández

Director del Dpto. de Desarrollo de Servitux