Documentación de Laravel 10.x
Aquí encontrarás fragmentos de código de Laravel y consejos útiles sobre desarrollo web.
El generador de consultas de la base de datos de Laravel proporciona una interfaz fluida y conveniente para crear y ejecutar consultas de base de datos. Puede usarse para realizar la mayoría de las operaciones de base de datos en tu aplicación y funciona perfectamente con todos los sistemas de base de datos compatibles con Laravel.
El generador de consultas de Laravel utiliza la vinculación de parámetros de PDO para proteger tu aplicación contra ataques de inyección SQL. No es necesario limpiar o sanear cadenas que se pasen al generador de consultas como vinculaciones de consulta.
Advertencia PDO no admite la vinculación de nombres de columnas. Por lo tanto, nunca debes permitir que la entrada del usuario dicte los nombres de las columnas referenciadas por tus consultas, incluidas las columnas "order by".
Puedes usar el método table
proporcionado por la fachada DB
para comenzar una consulta. El método table
devuelve una instancia de generador de consultas fluido para la tabla dada, lo que te permite encadenar más restricciones en la consulta y finalmente recuperar los resultados de la consulta usando el método get
:
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller;use Illuminate\Support\Facades\DB;use Illuminate\View\View; class UserController extends Controller{ /** * Muestra una lista de todos los usuarios de la aplicación. */ public function index(): View { $users = DB::table('users')->get(); return view('user.index', ['users' => $users]); }}
El método get
devuelve una instancia de Illuminate\Support\Collection
que contiene los resultados de la consulta, donde cada resultado es una instancia del objeto PHP stdClass
. Puedes acceder al valor de cada columna accediendo a la columna como una propiedad del objeto:
use Illuminate\Support\Facades\DB; $users = DB::table('users')->get(); foreach ($users as $user) { echo $user->name;}
Nota Las colecciones de Laravel proporcionan una variedad de métodos extremadamente poderosos para mapear y reducir datos. Para obtener más información sobre las colecciones de Laravel, consulta la documentación de colecciones.
Si solo necesitas recuperar una sola fila de una tabla de base de datos, puedes usar el método first
del facade DB
. Este método devolverá un solo objeto stdClass
:
$user = DB::table('users')->where('name', 'John')->first(); return $user->email;
Si no necesitas una fila completa, puedes extraer un solo valor de un registro utilizando el método value
. Este método devolverá el valor de la columna directamente:
$email = DB::table('users')->where('name', 'John')->value('email');
Para recuperar una sola fila por el valor de su columna id
, utiliza el método find
:
$user = DB::table('users')->find(3);
Si deseas recuperar una instancia de Illuminate\Support\Collection
que contenga los valores de una sola columna, puedes usar el método pluck
. En este ejemplo, recuperaremos una colección de títulos de usuario:
use Illuminate\Support\Facades\DB; $titles = DB::table('users')->pluck('title'); foreach ($titles as $title) { echo $title;}
Puedes especificar la columna que la colección resultante debería usar como sus claves proporcionando un segundo argumento al método pluck
:
$titles = DB::table('users')->pluck('title', 'name'); foreach ($titles as $name => $title) { echo $title;}
Si necesitas trabajar con miles de registros de bases de datos, considera usar el método chunk
proporcionado por la fachada DB
. Este método recupera un pequeño fragmento de resultados a la vez y alimenta cada fragmento en un cierre para su procesamiento. Por ejemplo, recuperemos toda la tabla de users
en fragmentos de 100 registros a la vez:
use Illuminate\Support\Collection;use Illuminate\Support\Facades\DB; DB::table('users')->orderBy('id')->chunk(100, function (Collection $users) { foreach ($users as $user) { // ... }});
Puedes evitar que se procesen más fragmentos devolviendo false
desde el cierre:
DB::table('users')->orderBy('id')->chunk(100, function (Collection $users) { // Procesa los registros... return false;});
Si estás actualizando registros de bases de datos mientras fragmentas resultados, tus resultados fragmentados podrían cambiar de maneras inesperadas. Si planeas actualizar los registros recuperados mientras fragmentas, siempre es mejor usar el método chunkById
en su lugar. Este método paginará automáticamente los resultados según la clave primaria del registro:
DB::table('users')->where('active', false) ->chunkById(100, function (Collection $users) { foreach ($users as $user) { DB::table('users') ->where('id', $user->id) ->update(['active' => true]); } });
Advertencia Al actualizar o eliminar registros dentro del callback de chunk, cualquier cambio en la clave primaria o las claves foráneas podría afectar la consulta de chunk. Esto podría resultar en que los registros no se incluyan en los resultados fragmentados.
El método lazy
funciona de manera similar al método chunk
en el sentido de que ejecuta la consulta en fragmentos. Sin embargo, en lugar de pasar cada fragmento a un callback, el método lazy()
devuelve una LazyCollection
, que te permite interactuar con los resultados como un solo flujo:
use Illuminate\Support\Facades\DB; DB::table('users')->orderBy('id')->lazy()->each(function (object $user) { // ...});
Nuevamente, si planeas actualizar los registros recuperados mientras iteras sobre ellos, es mejor usar los métodos lazyById
o lazyByIdDesc
. Estos métodos paginarán automáticamente los resultados según la clave primaria del registro:
DB::table('users')->where('active', false) ->lazyById()->each(function (object $user) { DB::table('users') ->where('id', $user->id) ->update(['active' => true]); });
Advertencia Al actualizar o eliminar registros mientras iteras sobre ellos, cualquier cambio en la clave primaria o las claves foráneas podría afectar la consulta de chunk. Esto podría resultar en que los registros no se incluyan en los resultados.
El generador de consultas también proporciona una variedad de métodos para recuperar valores agregados como count
, max
, min
, avg
y sum
. Puedes llamar a cualquiera de estos métodos después de construir tu consulta:
use Illuminate\Support\Facades\DB; $users = DB::table('users')->count(); $price = DB::table('orders')->max('price');
Por supuesto, puedes combinar estos métodos con otras cláusulas para ajustar cómo se calcula tu valor agregado:
$price = DB::table('orders') ->where('finalized', 1) ->avg('price');
En lugar de usar el método count
para determinar si existen registros que coincidan con las restricciones de tu consulta, puedes usar los métodos exists
y doesntExist
:
if (DB::table('orders')->where('finalized', 1)->exists()) { // ...} if (DB::table('orders')->where('finalized', 1)->doesntExist()) { // ...}
No siempre necesitas seleccionar todas las columnas de una tabla de base de datos. Utilizando el método select
, puedes especificar una cláusula "select" personalizada para la consulta:
use Illuminate\Support\Facades\DB; $users = DB::table('users') ->select('name', 'email as user_email') ->get();
El método distinct
te permite forzar que la consulta devuelva resultados distintos:
$users = DB::table('users')->distinct()->get();
Si ya tienes una instancia del generador de consultas y deseas agregar una columna a su cláusula de selección existente, puedes usar el método addSelect
:
$query = DB::table('users')->select('name'); $users = $query->addSelect('age')->get();
En ocasiones, es posible que necesites insertar una cadena arbitraria en una consulta. Para crear una expresión de cadena sin procesar, puedes usar el método raw
proporcionado por la fachada DB
:
$users = DB::table('users') ->select(DB::raw('count(*) as user_count, status')) ->where('status', '<>', 1) ->groupBy('status') ->get();
Advertencia Las declaraciones sin procesar se inyectarán en la consulta como cadenas, por lo que debes tener mucho cuidado de evitar crear vulnerabilidades de inyección de SQL.
En lugar de usar el método DB::raw
, también puedes usar los siguientes métodos para insertar una expresión sin procesar en varias partes de tu consulta. Recuerda, Laravel no puede garantizar que cualquier consulta que utilice expresiones sin procesar esté protegida contra vulnerabilidades de inyección SQL.
selectRaw
El método selectRaw
se puede usar en lugar de addSelect(DB::raw(/* ... */))
. Este método acepta un array opcional de vinculaciones como segundo argumento:
$orders = DB::table('orders') ->selectRaw('price * ? as price_with_tax', [1.0825]) ->get();
whereRaw / orWhereRaw
Los métodos whereRaw
y orWhereRaw
se pueden usar para inyectar una cláusula "where" sin procesar en tu consulta. Estos métodos aceptan un array opcional de vinculaciones como su segundo argumento:
$orders = DB::table('orders') ->whereRaw('price > IF(state = "TX", ?, 100)', [200]) ->get();
havingRaw / orHavingRaw
Los métodos havingRaw
y orHavingRaw
se pueden utilizar para proporcionar una cadena sin procesar como el valor de la cláusula "having". Estos métodos aceptan un array opcional de vinculaciones como su segundo argumento:
$orders = DB::table('orders') ->select('department', DB::raw('SUM(price) as total_sales')) ->groupBy('department') ->havingRaw('SUM(price) > ?', [2500]) ->get();
orderByRaw
El método orderByRaw
se puede utilizar para proporcionar una cadena sin procesar como el valor de la cláusula "order by":
$orders = DB::table('orders') ->orderByRaw('updated_at - created_at DESC') ->get();
groupByRaw
El método groupByRaw
se puede utilizar para proporcionar una cadena sin procesar como el valor de la cláusula group by
:
$orders = DB::table('orders') ->select('city', 'state') ->groupByRaw('city, state') ->get();
El generador de consultas también se puede utilizar para agregar cláusulas de unión a tus consultas. Para realizar un "inner join" básico, puedes usar el método join
en una instancia del generador de consultas. El primer argumento pasado al método join
es el nombre de la tabla a la que necesitas unirte, mientras que los argumentos restantes especifican las restricciones de columnas para la unión. Incluso puedes unir varias tablas en una sola consulta:
use Illuminate\Support\Facades\DB; $users = DB::table('users') ->join('contacts', 'users.id', '=', 'contacts.user_id') ->join('orders', 'users.id', '=', 'orders.user_id') ->select('users.*', 'contacts.phone', 'orders.price') ->get();
Si deseas realizar un "left join" o "right join" en lugar de un "inner join", utiliza los métodos leftJoin
o rightJoin
. Estos métodos tienen la misma firma que el método join
:
$users = DB::table('users') ->leftJoin('posts', 'users.id', '=', 'posts.user_id') ->get(); $users = DB::table('users') ->rightJoin('posts', 'users.id', '=', 'posts.user_id') ->get();
Puedes usar el método crossJoin
para realizar una "cross join". Las "cross join" generan un producto cartesiano entre la primera tabla y la tabla unida:
$sizes = DB::table('sizes') ->crossJoin('colors') ->get();
También puedes especificar cláusulas de unión más avanzadas. Para empezar, pasa un cierre como segundo argumento al método join
. El cierre recibirá una instancia de Illuminate\Database\Query\JoinClause
que te permite especificar restricciones en la cláusula "join":
DB::table('users') ->join('contacts', function (JoinClause $join) { $join->on('users.id', '=', 'contacts.user_id')->orOn(/* ... */); }) ->get();
Si deseas usar una cláusula "where" en tus uniones, puedes usar los métodos where
y orWhere
proporcionados por la instancia JoinClause
. En lugar de comparar dos columnas, estos métodos compararán la columna contra un valor:
DB::table('users') ->join('contacts', function (JoinClause $join) { $join->on('users.id', '=', 'contacts.user_id') ->where('contacts.user_id', '>', 5); }) ->get();
Puedes usar los métodos joinSub
, leftJoinSub
y rightJoinSub
para unir una consulta a una subconsulta. Cada uno de estos métodos recibe tres argumentos: la subconsulta, su alias de tabla y un cierre que define las columnas relacionadas. En este ejemplo, recuperaremos una colección de usuarios donde cada registro de usuario también contiene la marca de tiempo created_at
de la publicación de blog más reciente del usuario:
$latestPosts = DB::table('posts') ->select('user_id', DB::raw('MAX(created_at) as last_post_created_at')) ->where('is_published', true) ->groupBy('user_id'); $users = DB::table('users') ->joinSub($latestPosts, 'latest_posts', function (JoinClause $join) { $join->on('users.id', '=', 'latest_posts.user_id'); })->get();
El generador de consultas también proporciona un método conveniente para "unir" dos o más consultas. Por ejemplo, puedes crear una consulta inicial y usar el método union
para unirla con más consultas:
use Illuminate\Support\Facades\DB; $first = DB::table('users') ->whereNull('first_name'); $users = DB::table('users') ->whereNull('last_name') ->union($first) ->get();
Además del método union
, el generador de consultas proporciona un método unionAll
. Las consultas combinadas con el método unionAll
no eliminarán sus resultados duplicados. El método unionAll
tiene la misma firma de método que el método union
.
Puedes usar el método where
del generador de consultas para agregar cláusulas "where" a la consulta. La llamada más básica al método where
requiere tres argumentos. El primer argumento es el nombre de la columna. El segundo argumento es un operador, que puede ser cualquiera de los operadores admitidos por la base de datos. El tercer argumento es el valor con el que comparar el valor de la columna.
Por ejemplo, la siguiente consulta recupera usuarios donde el valor de la columna votes
es igual a 100
y el valor de la columna age
es mayor que 35
:
$users = DB::table('users') ->where('votes', '=', 100) ->where('age', '>', 35) ->get();
Para mayor comodidad, si deseas verificar que una columna es =
a un valor dado, puedes pasar el valor como segundo argumento al método where
. Laravel asumirá que deseas usar el operador =
:
$users = DB::table('users')->where('votes', 100)->get();
Como se mencionó anteriormente, puedes usar cualquier operador admitido por tu sistema de base de datos:
$users = DB::table('users') ->where('votes', '>=', 100) ->get(); $users = DB::table('users') ->where('votes', '<>', 100) ->get(); $users = DB::table('users') ->where('name', 'like', 'T%') ->get();
También puedes pasar un array de condiciones a la función where
. Cada elemento del array debe ser un array que contenga los tres argumentos que se pasan típicamente al método where
:
$users = DB::table('users')->where([ ['status', '=', '1'], ['subscribed', '<>', '1'],])->get();
Advertencia PDO no admite la vinculación de nombres de columnas. Por lo tanto, nunca debes permitir que la entrada del usuario dicte los nombres de las columnas referenciadas por tus consultas, incluidas las columnas "order by".
Al encadenar llamadas al método where
del generador de consultas, las cláusulas "where" se unirán utilizando el operador and
. Sin embargo, puedes usar el método orWhere
para unir una cláusula a la consulta usando el operador or
. El método orWhere
acepta los mismos argumentos que el método where
:
$users = DB::table('users') ->where('votes', '>', 100) ->orWhere('name', 'John') ->get();
Si necesitas agrupar una condición "or" entre paréntesis, puedes pasar un cierre como primer argumento al método orWhere
:
$users = DB::table('users') ->where('votes', '>', 100) ->orWhere(function (Builder $query) { $query->where('name', 'Abigail') ->where('votes', '>', 50); }) ->get();
El ejemplo anterior producirá el siguiente SQL:
select * from users where votes > 100 or (name = 'Abigail' and votes > 50)
Advertencia Siempre debes agrupar las llamadas a
orWhere
para evitar comportamientos inesperados cuando se aplican ámbitos globales.
Los métodos whereNot
y orWhereNot
se pueden usar para negar un grupo dado de restricciones de consulta. Por ejemplo, la siguiente consulta excluye productos que están en oferta o que tienen un precio inferior a diez:
$products = DB::table('products') ->whereNot(function (Builder $query) { $query->where('clearance', true) ->orWhere('price', '<', 10); }) ->get();
Laravel también admite consultas de tipos de columna JSON en bases de datos que admiten tipos de columna JSON. Actualmente, esto incluye MySQL 5.7+, PostgreSQL, SQL Server 2016 y SQLite 3.39.0 (con la extensión JSON1). Para consultar una columna JSON, usa el operador ->
:
$users = DB::table('users') ->where('preferences->dining->meal', 'salad') ->get();
Puedes usar whereJsonContains
para consultar matrices JSON. Esta función no es compatible con versiones de bases de datos SQLite anteriores a 3.38.0:
$users = DB::table('users') ->whereJsonContains('options->languages', 'en') ->get();
Si tu aplicación utiliza las bases de datos MySQL o PostgreSQL, puedes pasar un array de valores al método whereJsonContains
:
$users = DB::table('users') ->whereJsonContains('options->languages', ['en', 'de']) ->get();
Puedes usar el método whereJsonLength
para consultar matrices JSON por su longitud:
$users = DB::table('users') ->whereJsonLength('options->languages', 0) ->get(); $users = DB::table('users') ->whereJsonLength('options->languages', '>', 1) ->get();
whereBetween / orWhereBetween
El método whereBetween
verifica que el valor de una columna esté entre dos valores:
$users = DB::table('users') ->whereBetween('votes', [1, 100]) ->get();
whereNotBetween / orWhereNotBetween
El método whereNotBetween
verifica que el valor de una columna esté fuera de dos valores:
$users = DB::table('users') ->whereNotBetween('votes', [1, 100]) ->get();
whereBetweenColumns / whereNotBetweenColumns / orWhereBetweenColumns / orWhereNotBetweenColumns
El método whereBetweenColumns
verifica que el valor de una columna esté entre los dos valores de dos columnas en la misma fila de la tabla:
$patients = DB::table('patients') ->whereBetweenColumns('weight', ['minimum_allowed_weight', 'maximum_allowed_weight']) ->get();
El método whereNotBetweenColumns
verifica que el valor de una columna esté fuera de los dos valores de dos columnas en la misma fila de la tabla:
$patients = DB::table('patients') ->whereNotBetweenColumns('weight', ['minimum_allowed_weight', 'maximum_allowed_weight']) ->get();
whereIn / whereNotIn / orWhereIn / orWhereNotIn
El método whereIn
verifica que el valor de una columna dada esté contenido dentro del array dado:
$users = DB::table('users') ->whereIn('id', [1, 2, 3]) ->get();
El método whereNotIn
verifica que el valor de la columna dada no esté contenido en el array dado:
$users = DB::table('users') ->whereNotIn('id', [1, 2, 3]) ->get();
También puedes proporcionar un objeto de consulta como segundo argumento del método whereIn
:
$activeUsers = DB::table('users')->select('id')->where('is_active', 1); $users = DB::table('comments') ->whereIn('user_id', $activeUsers) ->get();
El ejemplo anterior producirá el siguiente SQL:
select * from comments where user_id in ( select id from users where is_active = 1)
Advertencia Si estás agregando una gran cantidad de enlaces de enteros a tu consulta, los métodos
whereIntegerInRaw
owhereIntegerNotInRaw
se pueden usar para reducir significativamente el uso de memoria.
whereNull / whereNotNull / orWhereNull / orWhereNotNull
El método whereNull
verifica que el valor de la columna dada sea NULL
:
$users = DB::table('users') ->whereNull('updated_at') ->get();
El método whereNotNull
verifica que el valor de la columna no sea NULL
:
$users = DB::table('users') ->whereNotNull('updated_at') ->get();
whereDate / whereMonth / whereDay / whereYear / whereTime
El método whereDate
se puede usar para comparar el valor de una columna con una fecha:
$users = DB::table('users') ->whereDate('created_at', '2016-12-31') ->get();
El método whereMonth
se puede usar para comparar el valor de una columna con un mes específico:
$users = DB::table('users') ->whereMonth('created_at', '12') ->get();
El método whereDay
se puede usar para comparar el valor de una columna con un día específico del mes:
$users = DB::table('users') ->whereDay('created_at', '31') ->get();
El método whereYear
se puede usar para comparar el valor de una columna con un año específico:
$users = DB::table('users') ->whereYear('created_at', '2016') ->get();
El método whereTime
se puede usar para comparar el valor de una columna con una hora específica:
$users = DB::table('users') ->whereTime('created_at', '=', '11:20:45') ->get();
whereColumn / orWhereColumn
El método whereColumn
se puede usar para verificar que dos columnas son iguales:
$users = DB::table('users') ->whereColumn('first_name', 'last_name') ->get();
También puedes pasar un operador de comparación al método whereColumn
:
$users = DB::table('users') ->whereColumn('updated_at', '>', 'created_at') ->get();
También puedes pasar un array de comparaciones de columnas al método whereColumn
. Estas condiciones se unirán utilizando el operador and
:
$users = DB::table('users') ->whereColumn([ ['first_name', '=', 'last_name'], ['updated_at', '>', 'created_at'], ])->get();
A veces, es posible que necesites agrupar varias cláusulas "where" dentro de paréntesis para lograr el agrupamiento lógico deseado de tu consulta. De hecho, generalmente siempre debes agrupar las llamadas al método orWhere
en paréntesis para evitar un comportamiento inesperado de la consulta. Para lograr esto, puedes pasar un cierre al método where
:
$users = DB::table('users') ->where('name', '=', 'John') ->where(function (Builder $query) { $query->where('votes', '>', 100) ->orWhere('title', '=', 'Admin'); }) ->get();
Como puedes ver, pasar un cierre al método where
instruye al generador de consultas a comenzar un grupo de restricciones. El cierre recibirá una instancia del generador de consultas que puedes usar para establecer las restricciones que deben estar contenidas dentro del grupo de paréntesis. El ejemplo anterior producirá el siguiente SQL:
select * from users where name = 'John' and (votes > 100 or title = 'Admin')
Advertencia Siempre debes agrupar las llamadas a
orWhere
para evitar comportamientos inesperados cuando se aplican ámbitos globales.
El método whereExists
te permite escribir cláusulas SQL "where exists". El método whereExists
acepta un cierre que recibirá una instancia de generador de consultas, lo que te permite definir la consulta que se debe colocar dentro de la cláusula "exists":
$users = DB::table('users') ->whereExists(function (Builder $query) { $query->select(DB::raw(1)) ->from('orders') ->whereColumn('orders.user_id', 'users.id'); }) ->get();
Alternativamente, puedes proporcionar un objeto de consulta al método whereExists
en lugar de un cierre:
$orders = DB::table('orders') ->select(DB::raw(1)) ->whereColumn('orders.user_id', 'users.id'); $users = DB::table('users') ->whereExists($orders) ->get();
Ambos ejemplos anteriores producirán el siguiente SQL:
select * from userswhere exists ( select 1 from orders where orders.user_id = users.id)
En ocasiones, es posible que necesites construir una cláusula "where" que compare los resultados de una subconsulta con un valor dado. Puedes lograr esto pasando un cierre y un valor al método where
. Por ejemplo, la siguiente consulta recuperará todos los usuarios que tienen una "membresía" reciente de un tipo dado;
use App\Models\User;use Illuminate\Database\Query\Builder; $users = User::where(function (Builder $query) { $query->select('type') ->from('membership') ->whereColumn('membership.user_id', 'users.id') ->orderByDesc('membership.start_date') ->limit(1);}, 'Pro')->get();
O bien, es posible que necesites construir una cláusula "where" que compare una columna con los resultados de una subconsulta. Puedes lograr esto pasando una columna, un operador y un cierre al método where
. Por ejemplo, la siguiente consulta recuperará todos los registros de ingresos donde la cantidad es menor que el promedio;
use App\Models\Income;use Illuminate\Database\Query\Builder; $incomes = Income::where('amount', '<', function (Builder $query) { $query->selectRaw('avg(i.amount)')->from('incomes as i');})->get();
Advertencia Las cláusulas where de texto completo actualmente son compatibles con MySQL y PostgreSQL.
Los métodos whereFullText
y orWhereFullText
se pueden utilizar para agregar cláusulas "where" de texto completo a una consulta para columnas que tienen índices de texto completo. Estos métodos se transformarán en el SQL adecuado para el sistema de base de datos subyacente por Laravel. Por ejemplo, se generará una cláusula MATCH AGAINST
para aplicaciones que utilizan MySQL:
$users = DB::table('users') ->whereFullText('bio', 'web developer') ->get();
orderBy
El método orderBy
te permite ordenar los resultados de la consulta por una columna dada. El primer argumento aceptado por el método orderBy
debe ser la columna por la cual deseas ordenar, mientras que el segundo argumento determina la dirección de la ordenación y puede ser asc
o desc
:
$users = DB::table('users') ->orderBy('name', 'desc') ->get();
Para ordenar por varias columnas, simplemente puedes invocar orderBy
tantas veces como sea necesario:
$users = DB::table('users') ->orderBy('name', 'desc') ->orderBy('email', 'asc') ->get();
latest
y oldest
Los métodos latest
y oldest
te permiten ordenar fácilmente los resultados por fecha. Por defecto, el resultado se ordenará por la columna created_at
de la tabla. O bien, puedes pasar el nombre de la columna por la cual deseas ordenar:
$user = DB::table('users') ->latest() ->first();
El método inRandomOrder
se puede utilizar para ordenar los resultados de la consulta de forma aleatoria. Por ejemplo, puedes usar este método para obtener un usuario aleatorio:
$randomUser = DB::table('users') ->inRandomOrder() ->first();
El método reorder
elimina todas las cláusulas "order by" que se hayan aplicado previamente a la consulta:
$query = DB::table('users')->orderBy('name'); $unorderedUsers = $query->reorder()->get();
Puedes pasar una columna y dirección al llamar al método reorder
para eliminar todas las cláusulas "order by" existentes y aplicar un orden completamente nuevo a la consulta:
$query = DB::table('users')->orderBy('name'); $usersOrderedByEmail = $query->reorder('email', 'desc')->get();
groupBy
y having
Como podrías esperar, los métodos groupBy
y having
se pueden utilizar para agrupar los resultados de la consulta. La firma del método having
es similar a la del método where
:
$users = DB::table('users') ->groupBy('account_id') ->having('account_id', '>', 100) ->get();
Puedes usar el método havingBetween
para filtrar los resultados dentro de un rango dado:
$report = DB::table('orders') ->selectRaw('count(id) as number_of_orders, customer_id') ->groupBy('customer_id') ->havingBetween('number_of_orders', [5, 15]) ->get();
Puedes pasar varios argumentos al método groupBy
para agrupar por varias columnas:
$users = DB::table('users') ->groupBy('first_name', 'status') ->having('account_id', '>', 100) ->get();
Para construir declaraciones having
más avanzadas, consulta el método havingRaw
.
skip
y take
Puedes usar los métodos skip
y take
para limitar la cantidad de resultados devueltos por la consulta o para omitir un número determinado de resultados en la consulta:
$users = DB::table('users')->skip(10)->take(5)->get();
Alternativamente, puedes usar los métodos limit
y offset
. Estos métodos son funcionalmente equivalentes a los métodos take
y skip
, respectivamente:
$users = DB::table('users') ->offset(10) ->limit(5) ->get();
A veces, es posible que desees que ciertas cláusulas de consulta se apliquen a una consulta en función de otra condición. Por ejemplo, es posible que solo desees aplicar una declaración where
si un determinado valor de entrada está presente en la solicitud HTTP entrante. Puedes lograr esto usando el método when
:
$role = $request->string('role'); $users = DB::table('users') ->when($role, function (Builder $query, string $role) { $query->where('role_id', $role); }) ->get();
El método when
solo ejecuta el cierre dado cuando el primer argumento es true
. Si el primer argumento es false
, el cierre no se ejecutará. Entonces, en el ejemplo anterior, el cierre dado al método when
solo se invocará si el campo role
está presente en la solicitud entrante y evalúa a true
.
Puedes pasar otro cierre como tercer argumento al método when
. Este cierre solo se ejecutará si el primer argumento se evalúa como false
. Para ilustrar cómo se puede usar esta característica, la usaremos para configurar el orden predeterminado de una consulta:
$sortByVotes = $request->boolean('sort_by_votes'); $users = DB::table('users') ->when($sortByVotes, function (Builder $query, bool $sortByVotes) { $query->orderBy('votes'); }, function (Builder $query) { $query->orderBy('name'); }) ->get();
El generador de consultas también proporciona un método insert
que se puede utilizar para insertar registros en la tabla de la base de datos. El método insert
acepta un array de nombres de columna y valores:
DB::table('users')->insert([ 'votes' => 0]);
Puedes insertar varios registros a la vez pasando un array de arrays. Cada array representa un registro que se debe insertar en la tabla:
DB::table('users')->insert([]);
El método insertOrIgnore
ignorará errores al insertar registros en la base de datos. Al usar este método, debes tener en cuenta que los errores de registro duplicado se ignorarán y también se pueden ignorar otros tipos de errores según el motor de base de datos. Por ejemplo, insertOrIgnore
omitirá el modo estricto de MySQL:
DB::table('users')->insertOrIgnore([]);
El método insertUsing
insertará nuevos registros en la tabla utilizando una subconsulta para determinar los datos que se deben insertar:
DB::table('pruned_users')->insertUsing([ 'id', 'name', 'email', 'email_verified_at'], DB::table('users')->select( 'id', 'name', 'email', 'email_verified_at')->where('updated_at', '<=', now()->subMonth()));
Si la tabla tiene una ID con autoincremento, usa el método insertGetId
para insertar un registro y luego recuperar la ID:
$id = DB::table('users')->insertGetId();
Advertencia Cuando uses PostgreSQL, el método
insertGetId
espera que la columna de incremento automático se llameid
. Si deseas recuperar la ID de un "sequence" diferente, puedes pasar el nombre de la columna como segundo parámetro al métodoinsertGetId
.
El método upsert
intentará insertar registros que no existen y actualizar los registros que ya existen con nuevos valores que puedes especificar. El primer argumento del método consta de los valores a insertar o actualizar, mientras que el segundo argumento enumera la(s) columna(s) que identifican de manera única los registros dentro de la tabla asociada. El tercer y último argumento es un array de columnas que deben actualizarse si ya existe un registro coincidente en la base de datos:
DB::table('flights')->upsert( [ ['departure' => 'Oakland', 'destination' => 'San Diego', 'price' => 99], ['departure' => 'Chicago', 'destination' => 'New York', 'price' => 150] ], ['departure', 'destination'], ['price']);
En el ejemplo anterior, Laravel intentará insertar dos registros. Si ya existe un registro con los mismos valores de columna departure
y destination
, Laravel actualizará la columna price
de ese registro.
Advertencia Todos los motores de base de datos excepto SQL Server requieren que las columnas en el segundo argumento del método
upsert
tengan un índice "primary" o "unique". Además, el controlador de base de datos MySQL ignora el segundo argumento del métodoupsert
y siempre utiliza los índices "primary" y "unique" de la tabla para detectar registros existentes.
Además de insertar registros en la base de datos, el generador de consultas también puede actualizar registros existentes mediante el método update
. El método update
, al igual que el método insert
, acepta un array de pares de columnas y valores que indican las columnas que se actualizarán. El método update
devuelve la cantidad de filas afectadas. Puedes restringir la consulta update
usando cláusulas where
:
$affected = DB::table('users') ->where('id', 1) ->update(['votes' => 1]);
A veces, es posible que desees actualizar un registro existente en la base de datos o crearlo si no existe un registro coincidente. En este escenario, se puede utilizar el método updateOrInsert
. El método updateOrInsert
acepta dos argumentos: un array de condiciones por las cuales encontrar el registro y un array de pares de columnas y valores que indican las columnas que se actualizarán.
El método updateOrInsert
intentará localizar un registro coincidente en la base de datos utilizando las columnas y los valores del primer argumento. Si el registro existe, se actualizará con los valores del segundo argumento. Si no se puede encontrar el registro, se insertará un nuevo registro con los atributos combinados de ambos argumentos:
DB::table('users') ->updateOrInsert( ['votes' => '2'] );
Al actualizar una columna JSON, debes usar la sintaxis ->
para actualizar la clave adecuada en el objeto JSON. Esta operación es compatible con MySQL 5.7+ y PostgreSQL 9.5+:
$affected = DB::table('users') ->where('id', 1) ->update(['options->enabled' => true]);
El generador de consultas también proporciona métodos convenientes para incrementar o decrementar el valor de una columna dada. Ambos de estos métodos aceptan al menos un argumento: la columna a modificar. Se puede proporcionar un segundo argumento para especificar la cantidad por la cual se debe incrementar o decrementar la columna:
DB::table('users')->increment('votes'); DB::table('users')->increment('votes', 5); DB::table('users')->decrement('votes'); DB::table('users')->decrement('votes', 5);
Si es necesario, también puedes especificar columnas adicionales para actualizar durante la operación de incremento o decremento:
DB::table('users')->increment('votes', 1, ['name' => 'John']);
Además, puedes incrementar o decrementar múltiples columnas a la vez utilizando los métodos incrementEach
y decrementEach
:
DB::table('users')->incrementEach([ 'votes' => 5, 'balance' => 100,]);
El método delete
del generador de consultas se puede utilizar para eliminar registros de la tabla. El método delete
devuelve la cantidad de filas afectadas. Puedes restringir las declaraciones delete
agregando cláusulas "where" antes de llamar al método delete
:
$deleted = DB::table('users')->delete(); $deleted = DB::table('users')->where('votes', '>', 100)->delete();
Si deseas truncar una tabla completa, lo que eliminará todos los registros de la tabla y restablecerá el ID de autoincremento a cero, puedes usar el método truncate
:
DB::table('users')->truncate();
Al truncar una base de datos PostgreSQL, se aplicará el comportamiento CASCADE
. Esto significa que todos los registros relacionados con claves foráneas en otras tablas también se eliminarán.
El generador de consultas también incluye algunas funciones para ayudarte a lograr un "bloqueo pesimista" al ejecutar tus declaraciones select
. Para ejecutar una declaración con un "bloqueo compartido", puedes llamar al método sharedLock
. Un bloqueo compartido evita que las filas seleccionadas se modifiquen hasta que tu transacción se confirme:
DB::table('users') ->where('votes', '>', 100) ->sharedLock() ->get();
Alternativamente, puedes usar el método lockForUpdate
. Un bloqueo "for update" evita que los registros seleccionados se modifiquen o se seleccionen con otro bloqueo compartido:
DB::table('users') ->where('votes', '>', 100) ->lockForUpdate() ->get();
Puedes usar los métodos dd
y dump
mientras construyes una consulta para volcar las vinculaciones y SQL actuales. El método dd
mostrará la información de depuración y luego detendrá la ejecución de la solicitud. El método dump
mostrará la información de depuración pero permitirá que la solicitud continúe ejecutándose:
DB::table('users')->where('votes', '>', 100)->dd(); DB::table('users')->where('votes', '>', 100)->dump();
Los métodos dumpRawSql
y ddRawSql
se pueden invocar en una consulta para volcar el SQL de la consulta con todas las vinculaciones de parámetros correctamente sustituidas:
DB::table('users')->where('votes', '>', 100)->dumpRawSql(); DB::table('users')->where('votes', '>', 100)->ddRawSql();