#php #mysql #laravel
#php #MySQL #laravel
Вопрос:
Кто-нибудь может помочь объяснить, почему один из следующих запросов Laravel работает, а другой нет?
Первое, что работает:
$array = ( 1, 2, 3 ,4 );
$query->whereIn( 'status_id', $array );
Это работает так, как ожидалось. Однако, когда я пытаюсь передать функцию для построения моего массива:
$query->whereIn( 'status_id', function() use ( $statuses ){
$status_array = array();
foreach( $statuses as $status ){
$status_array[] = $status->status_id;
}
return $status_array;
});
Я получаю следующую ошибку:
Общая ошибка: 1096 Таблицы не используются (SQL: выберите *
jobs
откудаstatus_id
в (выберите *))
Я проверил, чтобы увидеть, что массив, который я создаю в закрытии, совпадает с работающим массивом, и это так. Я упускаю что-то фундаментальное относительно Where() и его функций закрытия? Могу ли я даже передать закрытие Where() ?
Комментарии:
1. Что произойдет, если вы выполните «return array(1, 2, 3, 4)» из функции — работает ли это?
Ответ №1:
Когда вы используете закрытие в whereIn()
, Laravel подумает, что вы будете выполнять вспомогательный запрос. Следовательно, вы видите другое select
in
внутри вашего сообщения об ошибке.
Вам нужно будет проанализировать ваш массив значений, прежде чем переходить к whereIn()
foreach ($statuses as $status) {
$status_array[] = $status->status_id;
}
$query->whereIn('status_id', $status_array);
Дополнительно: см. Ссылку на исходный код Laravel.
Illuminate Database Query Builder:
public function whereIn($column, $values, $boolean = 'and', $not = false)
{
...
if ($values instanceof Closure)
{
return $this->whereInSub($column, $values, $boolean, $not);
}
}
который вызывает whereInSub()
:
protected function whereInSub($column, Closure $callback, $boolean, $not)
{
$type = $not ? 'NotInSub' : 'InSub';
// To create the exists sub-select, we will actually create a query and call the
// provided callback with the query so the developer may set any of the query
// conditions they want for the in clause, then we'll put it in this array.
call_user_func($callback, $query = $this->newQuery());
$this->wheres[] = compact('type', 'column', 'query', 'boolean');
$this->mergeBindings($query);
return $this;
}
Комментарии:
1. Это то, что я в итоге сделал, используя комбинацию из ответа Shift Exchange выше. Принял этот ответ, поскольку вы также дали мне хорошее объяснение, почему все получилось не так, как я ожидал. Спасибо 🙂
Ответ №2:
В качестве связанного ответа, вместо запуска цикла для создания вашего списка — просто попросите Laravel сделать это за вас
$status_array= DB::table('status')->lists('status_id');
затем используйте его
$query->whereIn( 'status_id', $status_array );
Комментарии:
1. Спасибо, это прекрасная маленькая функция и экономит дополнительный foreach 🙂
Ответ №3:
Я думаю, что ваша функция возвращает массив, подобный этому:
[ 0 => status_id_value_0,
1 => status_id_value_1,
...
]
Попробуйте вернуть an array_values($status_array)
, чтобы проверить это.
В любом случае, попробуйте и это:
$query->whereIn( 'status_id',
array_values(
array_map(
function($pos){return $pos->status_id;},
$statuses
)
)
);
Я надеюсь, что у вас все работает нормально.
Ответ №4:
Вам необходимо преобразовать значение, разделенное запятыми, в массив, прежде чем переходить к Where.
и это также хорошо для любого динамического контента
foreach ($statuses as $status) {
$status_array[] = $status->status_id;
}
$query->whereIn('status_id', $status_array);