¿Qué es Tinker?
Tinker es una herramienta en línea de comandos para
hacer pruebas rápidas de PHP / Laravel, disponible desde Laravel 5.4.
Tinker permite probar a
la mayoría de las funciones disponibles en PHP y Laravel, sin tener que
alterar el código ni indicar los namespaces, así si tenemos un
modelo en "App\Models\Pruebas"
llamado Foo, podemos hacer una
consulta simplemente llamando a Foo,
sin indicar el namespace.
Trazas en el código vs uso de Tinker
Para ver el resultado de una consulta a la BD podríamos imprimir el
resultado con dd() o
dump() en el código que estamos
desarrollando o en una sesión de Laravel Tinker.
Tinker es cómodo y rápido, su
desventaja principal es una menor legibilidad en ciertos resultados
que la que obtendremos al imprimir las trazas en el navegador, por ejemplo,
al obtener una colección con Eloquent, verlo en consola es
notablemente menos legible.
A su favor, Tinker nos evita modificar
el código y tener que refrescar el navegador, lo que puede a veces incluso
alterar el estado de nuestra base de datos.
Uso de Tinker
Para usar Tinker, primero debe estar
instalado. La forma más sencilla de hacerlo es mediante el comando:
composer require laravel/tinker
Para iniciar Tinker (iniciar sesión de Tinker)
abrir la terminal y usar el comando:
y para salir:
Podemos ver el resultado de escribir código PHP
echo 'Hola mundo' . PHP_EOL;
Se muestra: Hola mundo
Podemos ver el resultado de consultas Eloquent
o aún mejor, simplemente con:
Así, podremos consultar ciertos datos o simplemente
probar si nuestras consultas funcionan, por ejemplo:
User::where('role', 'admin')->get(['id', 'created_at'])->first()
devuelve:
App\Models\User {#3051
id: 1,
created_at: "2019-08-25 00:00:00",
}
Nota: si usamos el método
dd() se cierra la sesión de Tinker.
Prueba con fechas y Carbon
$created_at = App\Models\User::find(1)->created_at;
\Carbon\Carbon::parse($created_at,
'Europe/Madrid')->format('d-m-Y, H:i:s');
\Carbon\Carbon::parse($created_at,
'Europe/Madrid')->isoFormat('DD-MM-YYYY, HH:mm:ss');
Fichero SQL - Volcado de la BD para las pruebas.
Plus: trazando el SQL en consultas Eloquent
Resulta que si ejecutamos una consulta Eloquent y la BD no está
accesible (no arrancamos los servicios Apache / MySql por ejemplo),
aparecerá un error SQLSTATE seguido de la consulta SQL completa.
Ejemplo: tratamos de obtener el primer usuario.
Resultado:
[!] Aliasing 'User' to 'App\Models\User' for this Tinker session.
Illuminate/Database/QueryException with message 'SQLSTATE[HY000] [2002]...
(SQL: select * from `users` limit 1)
Y esto puede ser muy útil cuando estamos montando consultas complejas...
Pero hay, quizá, opciones más flexibles que provocar el error
(que fue como me imagine que existían):
1. Usar el método toSql().
2. Usar el query log de Eloquent (bueno, este
ya lo había usado en el código).
3. Escuchar y volcar las consultas a la BD.
Uso de toSql()
Este método sustituye a ->all(),
->get(), ->first(),
... en su caso. Podemos perder el final de ciertas consultas, como
... LIMIT 1 (tendríamos que forzarlo con take(1))
y no aparecerán los parámetros, pero es el más cómodo de usar.
Ejemplos con toSql()
Nota: voy a indicar la consulta seguida
del resultado para acortar...
User::first()->toSql()
"select * from `users`"
User::take(1)->toSql()
"select * from `users` limit 1"
User::whereNull('deleted_at')->where('name', 'xxx')->toSql()
"select * from `users` where `deleted_at` is null and `name` = ? and `users`.`deleted_at` is null"
Uso de query log
Este método muestra más información que el anterior, como los parámetros pasados o el tiempo de ejecución de la consulta. Para usarlo lo activamos con el comando:
Y volcamos el resultado después de la consulta con:
Ejemplo con query log
>>> DB::enableQueryLog()
=> null
>>> User::whereNull('deleted_at')->where('name', 'xxx')->first()
[!] Aliasing 'User' to 'App\Models\User' for this Tinker session.
=> null
>>> DB::getQueryLog()
=> [
[
"query" => "select * from `users` where `deleted_at` is null and `name` = ? and `users`.`deleted_at` is null limit 1",
"bindings" => [
"xxx",
],
"time" => 19.0,
],
]
>>>
En cuanto al último método, que es similar a query log,
se puede escribir lo siguiente al principio de la sesión de Tinker
para que imprima la información pertinente, por ejemplo, la consulta:
User::get(['name', 'profession', 'gender'])
si previamente hemos escrito el comando de escucha y colcado los datos:
DB::listen(function ($query) {
dump($query->sql);
dump($query->bindings);
dump($query->time);
});
da como resultado:
"select `name`, `profession`, `gender` from `users`"
[]
1.0
=> Illuminate\Database\Eloquent\Collection {#2986
all: [
App\User {#2980
name: "foo",
profession: "web admin",
gender: "other",
},
App\User {#2983
name: "baz",
profession: "developer",
gender: null,
},
],
}