Почему переменная DB::raw изменяется из строки в целое число в Laravel 5.7

#mysql #laravel #laravel-5.7

#mysql — сервер #laravel #laravel-5.7 #mysql

Вопрос:

У меня есть следующая часть более крупного запроса elequent, который все работает, когда я не ввожу переменную в DB::raw.

 $tests->join('test_categories', function ($join) use($request) {
    $join->on('test_categories.id', '=', DB::raw('(select category_id
       from test_category
       join test_categories on test_category.category_id = test_categories.id
       where test_category.test_id = tests.id
       and test_categories.name = ?
       limit 1)', ['Cars']
    ));
});
  

Но когда SQL выполняется, он изменяет ‘?’ на 4, как в:

 and test_categories.name = 4
  

Вместо ожидаемого:

 and test_categories.name = 'Cars'
  

Будем признательны за любую помощь.

ОБНОВЛЕННЫЙ

Я также пробовал следующее ранее:

 $tests->join('test_categories', function ($join) use ($category) {
    $join->on('test_categories.id', '=', DB::raw("(select category_id
       from test_category
       join test_categories on test_category.category_id = test_categories.id
       where test_category.test_id = tests.id
       and test_categories.name = :category
       limit 1)",array('category' => $category)));
});
  

Но в запросе это просто выводит следующее:

 and test_categories.name = :category
  

Это приводит к ошибке «SQLSTATE[HY093]: недопустимый номер параметра: смешанные именованные и позиционные параметры».

Все та же проблема.

И еще один вариант, который использует ту же технику с функцией $join->on.

 $tests->join('test_categories', function ($join) use ($category) {
    $join->on('test_categories.id', '=', DB::raw("(select category_id
       from test_category
       join test_categories on test_category.category_id = test_categories.id
       where test_category.test_id = tests.id
       and test_categories.name = :category
       limit 1)"),array('category' => $category));
});
  

Это приводит к преобразованию массива ErrorException (E_NOTICE) в строку:

 protected function compileWheresToArray($query)
{
   return collect($query->wheres)->map(function ($where) use ($query) {
       return $where['boolean'].' '.$this->{"where{$where['type']}"}($query, $where);
        })->all();
}
  

Ответ №1:

Основываясь на этой ссылке, вы могли бы использовать

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

Комментарии:

1. Спасибо, @hoseinz3 Я тоже попробовал этот метод. Я могу только представить, что это работает только в DB:: select, а не в $join-> on (я использую здесь. Я обновил вопрос новыми выводами, но в любом случае спасибо.

Ответ №2:

Попробуйте заменить :category на ".$category." .

Не уверен, что это хорошая практика — делать это таким образом, но это должно сработать.

 $tests->join('test_categories', function ($join) use ($category) {
    $join->on('test_categories.id', '=', DB::raw("(select category_id
       from test_category
       join test_categories on test_category.category_id = test_categories.id
       where test_category.test_id = tests.id
       and test_categories.name = ".$category."
       limit 1)"));
});
  

Комментарии:

1. Спасибо, это аналогичное решение, которое у меня есть сейчас, но это не рекомендуется, поскольку это может сделать код восприимчивым к SQL-инъекции. В идеале я хотел бы использовать встроенные функции для обработки этого для повышения безопасности и наилучшей практики.