Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel query builder parameter binding

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])?

like image 773
alex Avatar asked Mar 12 '16 16:03

alex


People also ask

What is a query builder in Laravel?

Laravel's database query builder provides a convenient, fluent interface to creating and running database queries. It can be used to perform most database operations in your application and works on all supported database systems.

How to bind column name in Laravel Query Builder using PDO?

Laravel query builder use PDO parameter bindings but PDO does not support binding column name. $users=DB::table ('users')->pluck ('name'); return $users;

What can I do with it in Laravel?

It can be used to perform most database operations in your application and works perfectly with all of Laravel's supported database systems. The Laravel query builder uses PDO parameter binding to protect your application against SQL injection attacks.

What is Laravel database?

Database: Query Builder - Laravel - The PHP Framework For Web Artisans Laravel is a PHP web application framework with expressive, elegant syntax. We’ve already laid the foundation — freeing you to create without sweating the small things.


2 Answers

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.

like image 104
tremby Avatar answered Oct 03 '22 05:10

tremby


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

like image 39
Ajith Gopi Avatar answered Oct 03 '22 03:10

Ajith Gopi