21

On Laravel, why do I get an error

Invalid parameter number: parameter was not defined

I have included all parameters.

When I tested directly on PHPMyAdmin, it work fine.

Code:

$results = \DB::select('SELECT client_id,
                               date_format(start_date,"%d/%m/%Y") as start_date,
                               date_format(end_date,"%d/%m/%Y") as end_date,
                               first_name, last_name, phone, postcode
                            FROM hire INNER JOIN client ON client.id = hire.client_id
                            where ((:sdate between start_date and end_date OR :edate between start_date and end_date) OR (:sdate <= start_date and end_date <= :edate)) AND car_id = :car_id', [
        'sdate'  => $start_date,
        'edate'  => $end_date,
        'car_id' => $car_id
    ]
);

Variable example:

$start_date = $inputs['start_date'];  //2015-10-27
$end_date = $inputs['end_date'];     //2015-10-27
$car_id = $inputs['car_id'];         //5
I'll-Be-Back
  • 10,530
  • 37
  • 110
  • 213

4 Answers4

44

Your query is failing because you are reusing parameters in your query. Laravel uses PDO for its SQL queries. According to the docs:

You cannot use a named parameter marker of the same name more than once in a prepared statement, unless emulation mode is on.

So even though they have the same value, you will have to rename those parameters.

$results = \DB::select('SELECT client_id,
                           date_format(start_date,"%d/%m/%Y") as start_date,
                           date_format(end_date,"%d/%m/%Y") as end_date,
                           first_name, last_name, phone, postcode
                        FROM hire INNER JOIN client ON client.id = hire.client_id
                        where ((:sdate between start_date and end_date OR :edate between start_date and end_date) OR (:sdate2 <= start_date and end_date <= :edate2)) AND car_id = :car_id', [
    'sdate'  => $start_date,
    'sdate2'  => $start_date,
    'edate'  => $end_date,
    'edate2'  => $end_date,
    'car_id' => $car_id
]
);
Andy Noelker
  • 10,949
  • 6
  • 35
  • 47
  • https://stackoverflow.com/a/48346164/470749 agrees with this. And naming separate params worked for me. Thanks. – Ryan Sep 03 '18 at 23:20
3

You're inserting all of your SQL inside of laravel's query builder select() method. You just need to utilize its other methods:

$select = [
    'client_id',
    'start_date',
    'end_date',
    'first_name',
    'last_name',
    'phone',
    'postcode'
];

$results = \DB::table('hire')
        ->join('client', 'client.id', '=', 'hire.client_id')
        ->select($select)
        ->where('car_id', $car_id)
        ->whereBetween('start_date', [$start_date, $end_date])
        ->orWhereBetween('end_date', [$start_date, $end_date])
        ->get();

These aren't all of your parameters, but it should get you started.

If you're not looking to use the query builder, try performing a raw($expression):

$results = \DB::raw('SELECT client_id,
                           date_format(start_date,"%d/%m/%Y") as start_date,
                           date_format(end_date,"%d/%m/%Y") as end_date,
                           first_name, last_name, phone, postcode
                        FROM hire INNER JOIN client ON client.id = hire.client_id
                        where ((:sdate between start_date and end_date OR :edate between start_date and end_date) OR (:sdate <= start_date and end_date <= :edate)) AND car_id = :car_id', [
        'sdate'  => $start_date,
        'edate'  => $end_date,
        'car_id' => $car_id
    ]
);
Steve Bauman
  • 8,165
  • 7
  • 40
  • 56
  • 1
    I understand but why should raw SQL fail in `select()` ? – I'll-Be-Back Nov 04 '15 at 16:10
  • 1
    You can try using `selectRaw($select)` (or `raw($expression)`) to run your statement, but using `select()` only adds columns to the current query builder. It won't process any of the SQL you're looking to run. Not to mention you're also not asking for any results using the `get()` method. https://github.com/laravel/framework/blob/5.1/src/Illuminate/Database/Query/Builder.php#L230 – Steve Bauman Nov 04 '15 at 16:14
  • 1
    While using the query builder or the Eloquent ORM is indeed preferred, adding raw SQL to the `select` method of the `DB` facade is completely valid. http://laravel.com/docs/5.1/database#running-queries – Andy Noelker Nov 04 '15 at 16:19
  • Had no idea! Thanks for clearing this up @Andy Noelker – Steve Bauman Nov 04 '15 at 16:21
1

app/config/database.php

add this in mysql array

'options'=> extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
                PDO::ATTR_EMULATE_PREPARES => true,
            ]) : [],
1

As Abdullah al Noman stated.

You can add the following statment to your database config file.

app/config/database.php

PDO::ATTR_EMULATE_PREPARES => true,

So it would look like this.

'options'=> extension_loaded('pdo_mysql') ? array_filter([
                PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
                PDO::ATTR_EMULATE_PREPARES => true,
            ]) : [],

In my case, I had multiple custom connections, so you need to make sure to find all PDO references and add them there.

After you do that, then in command.

php artisan optimize:clear
Richard Dev
  • 1,110
  • 7
  • 21