Вставка переменной в сырой SQL-запрос Laravel

Я нахожусь внутри функции в контроллере.

Итак, из формы я получаю значение для переменной, скажем:

$x = "whatever";

Затем мне нужно встроить эту переменную (а значит, и ее значение) в оператор WHERE. Если я жестко закодирую значение, это даст правильный результат, но я попытался всеми способами вставить эту переменную безуспешно. Что ж, если предположить, что мне удастся использовать эту переменную, тогда мне придется изучить привязку, чтобы избежать внедрения SQL, но пока, я бы сказал, посмотреть, можно ли использовать эту переменную в запросе.

Я пробовал, двойные кавычки, конкатенация. $vx . фигурные скобки {$x}, переменная обычная, как эта переменная $, но в некоторых случаях выдает синтаксические ошибки (конкатенация) или, если я просто встраиваю переменную, например, где author = $x, она говорит мне, что может не найти столбец с именем $ 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'
                           ));

2 ответа

Решение

Кажется, это простая проблема интерполяции переменных PHP.

DB:: raw хочет буквально RAW sql. Итак, есть пара проблем, которые необходимо исправить в передаваемой вами строке SQL.

  1. PHP Переменная интерполяция (вставка переменных в строку) происходит только если вы используете двойные кавычки вокруг строки. В одинарных кавычках он становится строковой константой.
  2. Если Author - это тип char/varchar, то синтаксис SQL требует кавычек вокруг строки в вашем выражении RAW SQL. Querybuilders обычно заботятся об этих проблемах для вас, но вы обходите их.

Таким образом, "фиксированная" версия этого будет:

$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"
                       ));

Как и любая интерполяция, это открывает вам возможность внедрения SQL, если интерполируемая переменная происходит из пользовательского ввода. Из исходного вопроса неясно, является ли это проблемой.

DB:: raw имеет опцию, которая позволяет вам вместо этого передавать массив параметров, который по своей природе безопасен для внедрения SQL. В этом случае решение будет:

$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)
                     ));

Что касается этого урока

$results = DB::select( DB::raw("SELECT * FROM some_table WHERE some_col = :somevariable"), array(
   'somevariable' => $someVariable,
 ));

Это один из примеров вставки переменной в необработанный sql laravel.

        $query_result = Event::select(
            DB::raw('(CASE WHEN status = "draft" THEN "draft" 
            WHEN events.end_time <= \''.$now.'\' THEN "closed"
            ELSE "available"
            END) AS status'))
            ->orderBy('status')
            ->get();
Другие вопросы по тегам