Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inserting a variable in a raw sql query Laravel

Tags:

sql

laravel

I am inside a function in a controller.

So from the Form, I get a value for a variable, say:

$x = "whatever";

Then I need to embed that variable (so, its value), in the WHERE statement. If I hardcode the value, it brings a correct result, but I have tried in all ways to insert that variable without success. Well, supposing that I manage to use that variable, then I will have to look into binding to avoid sql injection, but so far, I would say, see if that variable can get used in the query.

I have tried, double quotes, concatenation . $vx . , curly braces {$x}, the variable plain like this $variable, but either gives syntax errors in some cases, (concatenation), or if I just embed the variable like this where author = $x, it tells me that it can't find the column named $x

$x = "whatever";
$results = DB::select(DB::raw('SELECT 
                           t.id, t.AvgStyle, r.RateDesc
                       FROM (
                           SELECT
                               p.id, ROUND(AVG(s.Value)) AS AvgStyle
                           FROM posts p

                           INNER JOIN styles s
                               ON s.post_id = p.id
                           WHERE author = $x    
                           GROUP BY p.id
                       ) t
                       INNER JOIN rates r
                           ON r.digit = t.AvgStyle'
                           ));
like image 669
Arminius Avatar asked Jun 03 '16 15:06

Arminius


People also ask

How do you add a condition to a query in laravel?

$query = User::query(); // From Laravel 5.4 you can pass the same condition value as a parameter $query->when(request('role', false), function ($q, $role) { return $q->where('role_id', $role); }); $authors = $query->get();

What is DB :: Raw in laravel?

DB::raw() is used to make arbitrary SQL commands which aren't parsed any further by the query builder. They therefore can create a vector for attack via SQL injection. Check this ref. link, with more details: http://fideloper.com/laravel-raw-queries.

What is raw SQL query?

Raw SQL, sometimes also called native SQL, is the most basic, most low-level form of database interaction. You tell the database what to do in the language of the database. Most developers should know basics of SQL. This means how to CREATE tables and views, how to SELECT and JOIN data, how to UPDATE and DELETE data.

How can I use SQL query in laravel?

If you need to execute some SQL query, without processing any results, like INSERT or UPDATE without any parameters, you can use DB::statement(). In my experience, it's often used in database migrations, when some table structure changes and old data needs to be updated with a new structure.


2 Answers

This appears to be a simple PHP variable interpolation issue.

DB::raw() wants literally raw SQL. So there are a couple of issues that need to be fixed in the SQL string you are passing.

  1. PHP Variable interpolation (injecting variables into a string) only happens if you use double quotes around the string. With single quotes it becomes a string constant.
  2. If Author is a char/varchar, then SQL syntax requires quotes around the string in your raw SQL statement. Query builders typically take care of these issues for you, but you are going around them.

So the "fixed" version of this would be:

$x = "whatever";
$results = DB::select(DB::raw("SELECT 
                       t.id, t.AvgStyle, r.RateDesc
                   FROM (
                       SELECT
                           p.id, ROUND(AVG(s.Value)) AS AvgStyle
                       FROM posts p

                       INNER JOIN styles s
                           ON s.post_id = p.id
                       WHERE author = '$x'    
                       GROUP BY p.id
                   ) t
                   INNER JOIN rates r
                       ON r.digit = t.AvgStyle"
                   ));

Like all interpolation, this opens you up to the possibility of SQL injection if the variable being interpolated comes from user input. From the original question it is unclear whether this is a problem.

DB::select() has an option that allows you to pass an array of parameters that is inherently safe from SQL injection. In that case the solution would be:

$x = "whatever";
$results = DB::select(DB::raw("SELECT 
                       t.id, t.AvgStyle, r.RateDesc
                   FROM (
                       SELECT
                           p.id, ROUND(AVG(s.Value)) AS AvgStyle
                       FROM posts p

                       INNER JOIN styles s
                           ON s.post_id = p.id
                       WHERE author = :author
                       GROUP BY p.id
                   ) t
                   INNER JOIN rates r
                       ON r.digit = t.AvgStyle"
                   ),
                       array('author' => $x)
                   );
like image 149
gview Avatar answered Oct 24 '22 05:10

gview


Regarding this tutorial

$results = DB::select( DB::raw("SELECT * FROM some_table WHERE some_col = :somevariable"), array(
   'somevariable' => $someVariable,
 ));
like image 38
Roland Avatar answered Oct 24 '22 05:10

Roland