'Laravel query builder binding parameters more than once
I'm trying to bind the same value to some parameter in a raw query (Laravel 5.2)
//this is a non practical example ,only for clarify the question
DB::table('users as u')
->select('id')
->whereRaw('u.id > ? or u.id < ? or u.id = ?',[$id, $id, $id])
->first();
is there any way to bind the same parameters at once(prevent duplicating values in [$id, $id, $id]
)?
Solution 1:[1]
Use named parameters. They're covered in the documentation in the Running Raw SQL Queries section of the Database page, under the subheading Using Named Bindings. Quoting:
Instead of using
?
to represent your parameter bindings, you may execute a query using named bindings:$results = DB::select('select * from users where id = :id', ['id' => 1]);
In your case you ought to be able to run this:
DB::table('users as u')
->select('id')
->whereRaw('u.id > :id or u.id < :id or u.id = :id', [
'id' => 2,
])
->first();
But it seems Laravel throws a QueryException
with the message Invalid parameter number
. I've reported this as a bug.
If you really want to use whereRaw
you could instead build your array of parameters from a variable:
$id = 2;
DB::table('users as u')
->select('id')
->whereRaw('u.id > ? or u.id < ? or u.id = ?', [
$id, $id, $id,
])
->first();
Or use array_fill
to repeat the value for you:
$id = 2;
DB::table('users as u')
->select('id')
->whereRaw('u.id > ? or u.id < ? or u.id = ?', array_fill(0, 3, $id))
->first();
If you don't need whereRaw
you can instead use other features of the query builder and build the query bit by bit, with the parameter coming from a variable:
$id = 2;
DB::table('users')
->select('id')
->where('id', '>', $id)
->orWhere('id', '<', $id)
->orWhere('id', $id)
->first();
The query builder is quite powerful, and to get more complicated logic you can nest closures. See the relevant section of the docs for some examples.
Solution 2:[2]
As @tremby has answered, You can use
DB::table('users as u')
->select('id')
->whereRaw('u.id > :id or u.id < :id or u.id = :id',['id'=>2])
->first();
to use named binding.
Additionally, You have to set PDO::ATTR_EMULATE_PREPARES => true
in config/database.php
in order to get rid of the Invalid parameter number
exception, like:
config/database.php
'mysql' => [
'driver' => 'mysql',
...
'options' => [
PDO::ATTR_EMULATE_PREPARES => true,
],
],
Reference: https://github.com/laravel/framework/issues/12715#issuecomment-197013236
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | M Khalid Junaid |
Solution 2 | Ajith Gopi |