Getting started
Routing and controllers
Command line
Databases (SQL)
Databases (NoSQL)
Security
Packages
Learn more
Query builder
- Getting a query builder instance
- Fetching data
- Inserting data
- Updating data
- Deleting data
- Aggregates
- WHERE clauses
- WHERE BETWEEN clauses
- WHERE IN clauses
- WHERE IS NULL clauses
- WHERE EXISTS clauses
- JOIN clauses
- GROUP BY clauses
- HAVING clauses
- ORDER BY clauses
- LIMIT and OFFSET clauses
The query builder allows you to programmatically build SQL queries.
The query builder currently supports the following dialects:
- DB2
- Firebird
- MariaDB
- MySQL
- NuoDB
- Oracle
- PostgreSQL
- SQLite
- SQLServer
All queries executed by the query builder use prepared statements, thus mitigating the risk of SQL injections.
Getting a query builder instance
You can create a query builder instance using the Connection::builder()
method.
$query = $connection->builder();
You can also skip the call to the Connection::builder()
method using the Connection::table()
method.
$query = $conncetion->table('foobar');
Fetching data
Fetching all rows is done using the all
method.
$persons = $query->table('persons')->all();
// You can also specify which columns you want to include in the result set
$persons = $query->table('persons')->select(['name', 'email'])->all();
// To make a distinct selection use the distinct method
$persons = $query->table('persons')->select(['name', 'email'])->distinct()->all();
Selecting from the results of a subquery is also possible.
$persons = $query->table(function($query)
{
$query->table('persons')->select(['name'])->distinct();
})
->where('name', '!=', 'John Doe')
->all();
You can also use the Subquery class instead of a closure if you need a specific table alias.
$persons = $query->table
(
new Subquery
(
$connection->builder()->table('persons')->select(['name'])->distinct(), 'distinct_names'
)
)
->where('name', '!=', 'John Doe')
->all();
Advanced column selections can also be made using raw SQL and subqueries.
$persons = $query->table('persons')->select
(
[
'name',
'email',
new Raw("CASE gender WHEN 'm' THEN 'male' ELSE 'female' END AS gender"),
new Subquery
(
$connection->builder()->table('persons')->select([new Raw('AVG(age)'])), 'average_age'
)
]
)->all();
Make sure not to create SQL injection vectors when using raw sql in your query builder queries!
If you only want to retrieve a single row you can use the first
method.
$person = $query->table('persons')->where('id', '=', 1)->first();
Fetching the value of a single column is done using the column
method.
$email = $query->table('persons')->select(['email'])->where('id', '=', 1)->column();
// You can also use the following syntax
$email = $query->table('persons')->where('id', '=', 1)->column('email');
If you need to process large ammounts of data then the batch
method will help you limit the memory usage of your application. The default batch size is a 1000 records but you can override this using the optional second parameter.
You can also set the offset starting point and offset end point using the optional third and fourth parameters respectively. This is useful if you have parallel workers processing data.
$query->table('persons')->ascending('id')->batch(function($batch)
{
// Process the batch here
});
Inserting data
Inserting data is done using the insert
method.
$query->table('foobars')->insert(['field1' => 'foo', 'field2' => new DateTime()]);
You can also insert data using the insertAndGetId
method. It will create the record and return the generated auto increment id.
$query->table('foobars')->insertAndGetId(['field1' => 'foo', 'field2' => new DateTime()]);
When working with PostgreSQL the
insertAndGetId
method assumes that the sequence follows the default naming convention (<table_name>_<primary_key_name>_seq
) You can override the default primary key name (id
) by using the optional second parameter.
Updating data
Updating data is done using the update
method.
$query->table('foobars')
->where('id', '=', 10)
->update(['field1' => 'foo', 'field2' => 'bar', 'field3' => time()]);
There are also shortcuts for incrementing and decrementing column values:
$query->table('articles')->where('id', '=', 1)->increment('views');
$query->table('articles')->where('id', '=', 1)->increment('views', 10);
$query->table('shows')->where('id', '=', 1)->decrement('tickets')
$query->table('shows')->where('id', '=', 1)->decrement('tickets', 50);
Deleting data
Deleting data is done using the delete
method.
$query->table('articles')->where('id', '=', 10)->delete();
Aggregates
The query builder also includes a few handy shortcuts to the most common aggregate functions:
// Counting
$count = $query->table('persons')->count();
$count = $query->table('persons')->where('age', '>', 25)->count();
// Average value
$height = $query->table('persons')->avg('height');
$height = $query->table('persons')->where('age', '>', 25)->avg('height');
// Largest value
$height = $query->table('persons')->max('height');
$height = $query->table('persons')->where('age', '>', 25)->max('height');
// Smallest value
$height = $query->table('persons')->min('height');
$height = $query->table('persons')->where('age', '>', 25)->min('height');
// Sum
$height = $query->table('persons')->sum('height');
$height = $query->table('persons')->where('age', '>', 25)->sum('height');
WHERE clauses
where(), whereRaw(), orWhere(), orWhereRaw()
// SELECT * FROM `persons` WHERE `age` > 25
$persons = $query->table('persons')->where('age', '>', 25)->all();
// SELECT * FROM `persons` WHERE `age` > 25 OR `age` < 20
$persons = $query->table('persons')->where('age', '>', 25)->orWhere('age', '<', 20)->all();
// SELECT * FROM `persons` WHERE (`age` > 25 AND `height` > 180) AND `email` IS NOT NULL
$persons = $query->table('persons')
->where(function($query)
{
$query->where('age', '>', 25);
$query->where('height', '>', 180);
})
->notNull('email')
->all();
Make sure not to create SQL injection vectors when using raw sql in your query builder queries!
WHERE BETWEEN clauses
between(), orBetween(), notBetween(), orNotBetween()
// SELECT * FROM `persons` WHERE `age` BETWEEN 20 AND 25
$persons = $query->table('persons')->between('age', 20, 25)->all();
// SELECT * FROM `persons` WHERE `age` BETWEEN 20 AND 25 OR `age` BETWEEN 30 AND 35
$persons = $query->table('persons')->between('age', 20, 25)->orBetween('age', 30, 35)->all();
WHERE IN clauses
in(), orIn(), notIn(), orNotIn()
// SELECT * FROM `persons` WHERE `id` IN (1, 2, 3, 4, 5)
$persons = $query->table('persons')->in('id', [1, 2, 3, 4, 5])->all();
// SELECT * FROM `persons` WHERE `id` IN (SELECT `id` FROM `persons` WHERE `id` != 1)
$persons = $query->table('persons')
->in('id', function($query)
{
$query->table('persons')->select(['id'])->where('id', '!=', 1);
})
->all();
WHERE IS NULL clauses
null(), orNull(), notNull(), orNotNull()
// SELECT * FROM `persons` WHERE `address` IS NULL
$persons = $query->table('persons')->null('address')->all();
WHERE EXISTS clauses
exists(), orExists(), notExists(), orNotExists()
// SELECT * FROM `persons` WHERE EXISTS (SELECT * FROM `cars` WHERE `cars`.`person_id` = `persons`.`id`)
$persons = $query->table('persons')
->exists(function($query)
{
$query->table('cars')->whereRaw('cars.person_id', '=', 'persons.id');
})
->all();
JOIN clauses
join(), joinRaw(), leftJoin(), leftJoinRaw()
// SELECT * FROM `persons` INNER JOIN `phones` ON `persons`.`id` = `phones`.`user_id`
$persons = $query->table('persons')->join('phones', 'persons.id', '=', 'phones.user_id')->all();
// SELECT * FROM `persons` AS `u` INNER JOIN `phones` AS `p` ON
// `u`.`id` = `p`.`user_id` OR `u`.`phone_number` = `p`.`number`
$persons = $query->table('persons as u')
->join('phones as p', function($join)
{
$join->on('u.id', '=', 'p.user_id');
$join->orOn('u.phone_number', '=', 'p.number');
})
->all();
Make sure not to create SQL injection vectors when using raw sql in your query builder queries!
GROUP BY clauses
groupBy()
// SELECT `customer`, `order_date`, SUM(`order_price`) as `sum` FROM `orders` GROUP BY `customer`
$customers = $query->table('orders')
->select(['customer', new Raw('SUM(price) as sum')])
->groupBy('customer')
->all();
// SELECT `customer`, `order_date`, SUM(`order_price`) as `sum` FROM `orders` GROUP BY `customer`, `order_date`
$customers = $query->table('orders')
->select(['customer', 'order_date', new Raw('SUM(price) as sum')])
->groupBy(['customer', 'order_date'])
->all();
HAVING clauses
having(), orHaving()
// SELECT `customer`, SUM(`price`) AS `sum FROM `orders` GROUP BY `customer` HAVING SUM(`price`) < 2000
$customers = $query->table('orders')
->select(['customer', new Raw('SUM(price) as sum')])
->groupBy('customer')
->having(new Raw('SUM(price)'), '<', 2000)
->all();
ORDER BY clauses
orderBy(), orderByRaw(), descending(), descendingRaw(), ascending(), ascendingRaw()
// SELECT * FROM `persons` ORDER BY `name` ASC
$persons = $query->table('persons')->orderBy('name', 'asc')->all();
// SELECT * FROM `persons` ORDER BY `name` ASC
$persons = $query->table('persons')->ascending('name')->all();
// SELECT * FROM `persons` ORDER BY `name` DESC
$persons = $query->table('persons')->descending('name')->all();
// SELECT * FROM `persons` ORDER BY `name` ASC, `age` DESC
$persons = $query->table('persons')->orderBy('name', 'asc')->orderBy('age', 'desc')->all();
// SELECT * FROM `persons` ORDER BY `name`, `age` ASC
$persons = $query->table('persons')->orderBy(['name', 'age'], 'asc')->all();
Make sure not to create SQL injection vectors when using raw sql in your query builder queries!
LIMIT and OFFSET clauses
limit(), offset(), paginate()
// SELECT * FROM `persons` LIMIT 10
$persons = $query->table('persons')->limit(10)->all();
// SELECT * FROM `persons` LIMIT 10 OFFSET 10
$persons = $query->table('persons')->limit(10)->offset(10)->all();
You can also use a pagination instance to limit your results.
// SELECT * FROM `persons` LIMIT 10 OFFSET 0
$persons = $query->table('persons')->paginate($pagination)->all();