Como hemos visto anteriormente, es mucho más sencillo trabajar fechas y horas cuando lo hacemos con Carbon, el componente que extiende las funciones de la clase DateTime de PHP.

Sin embargo, cuando creamos cualquiera de los atributos temporales (TIMESTAMP, DATETIME, DATE, TIME) para una entidad en particular, por defecto no podemos usar toda la variedad de métodos que nos ofrece Carbon para este tipo de atributos. En este tutorial te enseñaremos cómo podemos corregir este problema.

Supongamos que queremos trabajar con una modelo llamado Event que tendrá como atributos el nombre del evento (name) y sus fechas de inicio y fin (started_at y finished_at).

Generando modelo y migración

Para generar el modelo Event con su migración, ejecutamos en la consola:

#
php artisan make:model Event -m

Como resultado, tendremos el nuevo modelo app/Models/Event.php con su archivo de migración create_events_table  en el directorio database/migrations.

Dentro de este archivo, agregamos el siguiente código en el método up para crear la tabla events:

//
public function up()
{
    Schema::create('events', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->dateTime('started_at');
        $table->dateTime('finished_at');
        $table->timestamps();
    });
}

Y luego ejecutamos las migraciones con:

#
php artisan migrate

Recuerda configurar las credenciales de tu base de datos en el archivo .env.

Aprende más sobre Eloquent ORM viendo las lecciones en video de nuestro «Curso de Eloquent ORM»

Ver más

Creando nuevo controlador de recursos

Ahora, vamos a generar el controlador app/Http/Controllers/EventController.php para trabajar con nuestro modelo:

#
php artisan make:controller EventController --resource

En el método create de este controlador retornaremos la vista para crear nuevos eventos:

//
public function create()
{
    return view('add-event');
}

Y luego, en routes/web.php añadimos la ruta de tipo resource de esta manera:

//
use App\Http\Controllers\EventController;

Route::resource('events', EventController::class);

Agregando vista

Ahora crearemos la vista add-event.blade.php en el directorio resources/views/:

<!-- HTML -->
<h1>New event</h1>

<form method="POST" action="{{ route('events.store') }}">
    @csrf

    <div class="form-group">
        <label for="name">Name: </label>
        <input type="text" name="name" id="name" class="form-control">
    </div>

    <div class="form-group">
        <label for="started_at">Started at: </label>
        <input type="date" name="started_at" id="started_at" class="form-control">
    </div>

    <div class="form-group">
        <label for="finished_at">Finished at: </label>
        <input type="date" name="finished_at" id="finished_at" class="form-control">
    </div>

    <button type="submit" class="btn btn-primary">Create</button>
</form>
<!-- HTML -->

Para ver esta vista, vamos a ejecutar en la consola php artisan serve y nos dirigimos a la URL http://127.0.0.1:8000/events/create:

formulario para crear nuevo evento

Usando el componente Carbon

Podemos pedirle a Eloquent que maneje los datos temporales como una instancia de Carbon. Para ello, en el archivo app/Models/Event.php añadimos dentro del array $dates los atributos que definimos en la migración started_at y finished_at, de la siguiente manera:

//
use Illuminate\Database\Eloquent\Model;

class Event extends Model
{
    protected $dates = [
        'started_at',
        'finished_at'
    ];
}

En este array deberían estar todos aquellos atributos de tipo temporal que queremos manipular como instancias de Carbon.

Una vez que Eloquent está consciente que es una columna que maneja fechas permite que su mutator haga las conversiones necesarias para que el valor se almacene correctamente en la base de datos. Así puedes asignar un valor UNIXTIMESTAMP (es decir, la cantidad de segundos transcurridos desde el 01-01-1970 a las 00:00:00 UTC), una cadena con la fecha completa en formato Y-m-d hh:mm:ss, la porción de fecha solamente en el formato Y-m-d, la porción de la hora solamente en formato hh:mm:ss, o, de forma más precisa, puedes pasarle una instancia de la propia clase Carbon e incluso de la clase padre DateTime de PHP.

Por defecto, Eloquent establece los atributos created_at y updated_at como instancias de Carbon y asigna sus valores automáticamente; pero si quieres desactivar este comportamiento lo que tienes que hacer es declarar la propiedad $timestamps a false en el modelo.

Veamos el siguiente ejemplo, en el método store de app/Http/Controllers/EventController.php.

<?php //...
use App\Models\Event; 

//...
public function store(Request $request, Event $event)
{
    $event->name = $request->name;
    $event->started_at = $request->started_at;
    $event->finished_at = $event->started_at->addMonth();

    $event->save();

    return $event;
}

El atributo started_at del tipo date de HTML dado por $request->started, contiene una cadena con la porción de la fecha solamente, por ejemplo "2020-11-26". Esto está dentro del grupo de valores posibles que espera el mutator para hacer la asignación de forma automática y con valores compatibles, en este caso el mutator será ejecutado cuando hagamos la operación de asignación del campo $event->started_at = $request->started_at.

Podemos apreciar también que la fecha $event->finished_at siempre tomará el valor de un mes luego de la fecha inicial. Esto puede que no sea lo que quieras en tu proyecto; sin embargo, la idea acá es ilustrar la utilidad de Carbon que nos permite, a través del método addMonth, aumentar el valor de otra fecha de una forma expresiva sin cálculos manuales. Este es por supuesto uno de los múltiples métodos que incluye Carbon para el manejo de fechas.

Finalmente podremos ver una salida en el navegador similar a ésta:

{
  "name": "Evento de inicio",
  "started_at": "2020-11-23T00:00:00.000000Z",
  "finished_at": "2020-12-23T00:00:00.000000Z"
}

Observa que la fecha envuelta en una instancia de Carbon, muestra tanto la porción de la fecha como la hora e incluso los microsegundos de precisión.

Para aprender más sobre el manejo de atributos dinámicos en Eloquent incluyendo fechas, puedes ver la sección de Eloquent Mutators en nuestra documentación del framework en español o ver nuestro nuevo Curso de Eloquent ORM.

Material relacionado

 

Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.