#mysql #laravel #if-statement
#mysql #laravel #if-оператор #if-statement
Вопрос:
У меня есть запрос, который работает в mysql, но при выполнении его в laravel я получаю неправильные результаты. обновление: версия Laravel — 4.2.
Запрос извлекает все книги, но если у книги есть «visibility_school» (логическое значение), то школа текущего пользователя должна соответствовать школе автора книги — поэтому я использовал для этого инструкцию IF.
Этот запрос mysql работает: (смотрите WHERE IF
Строку, где я жестко закодировал значение 2 ( schools.id = 2
) для сравнения для тестирования, обычно оно динамическое)
SELECT book.*, user.name AS name, user.school_class AS schoolClass, schools.name as
schoolName, count(DISTINCT book.id) AS overallCount,
AVG(book_rating.mark) AS rating
FROM book
LEFT JOIN user ON book.user_id = user.id
LEFT JOIN book_tag ON book.id = book_tag.book_id
LEFT JOIN book_rating ON book.id = book_rating.book_id
LEFT JOIN schools ON schools.id = user.school_id
WHERE IF(book.visibility_school = 1, IF(schools.id = 2, 1, 0), 1) = 1
AND book.published = 1
AND book.deleted = 0
GROUP BY book.id
При выполнении этого в построителе запросов Laravel мой код выглядит следующим образом:
$books = DB::table('book')
->select(DB::raw("book.*, user.name AS name, user.school_class AS schoolClass,
schools.name as schoolName,count(DISTINCT book.id) AS overallCount,
AVG(book_rating.mark) AS rating"))
->leftJoin('user', 'book.user_id', '=', 'user.id')
->leftJoin('book_tag', 'book.id', '=', 'book_tag.book_id')
->leftJoin('book_rating', 'book.id', '=', 'book_rating.book_id')
->leftJoin('schools', 'schools.id', '=', 'user.school_id')
->where(DB::raw("IF(book.visibility_school = 1, IF(schools.id = '?', 1, 0), 1) = 1"),$currentUserSchoolId)
->where('book.published',Book::STATUS_PUBLISHED)
->where('book.deleted',0)
->groupBy('book.id');
Запрос mysql правильно возвращает 5 опубликованных книг, и если я установлю schools.id = 3
, будет включена дополнительная книга, видимая только членам определенного школьного идентификатора.
Однако код laravel не возвращает книг, за двумя исключениями:
-
Если я установлю
schools.id = 0
, я получу 1 результат, одну книгу, видимую только членам определенной школы (у которой должен быть идентификатор 3). -
Если я установлю
schools.id = 1
— я получу 5 опубликованных книг. Если я задаю какие-либо другие идентификаторы, я не получаю результатов.
Нет никакой разницы, если я помещу $currentUserSchoolId
внутрь массива [$currentUserSchoolId]
. Также Book::STATUS_PUBLISHED
свойство равно 1, так что там нет разницы с версией кода mysql.
Таким образом, laravel, похоже, оценивает строку « where if
» как false, даже если visibility_school
значение не равно 1.
——— Обновить ———
После предложения я изменил where if
строку (а также добавил к ней: AND schools.id <> 0
):
->where(DB::raw("book.visibility_school <> 1 OR schools.id = '?' AND schools.id <> 0"),
$currentUserSchoolId)
Теперь я всегда получаю опубликованные книги, так что это хорошо, но я все еще не получаю книгу, видимую для соответствующего школьного идентификатора. Если я установил schools.id = 3
, я должен получить его, и он все еще работает в mysql. Но если я установлю для него значение 0 (и удалю И schools.id <> 0) Я тоже получаю эту книгу — поэтому laravel считает, что идентификатор школы по какой-то причине равен 0. Итак, это моя текущая проблема.
Комментарии:
1. Я думаю, что ваше состояние действительно
WHERE (book.visibility_school != 1 OR schools.id = 2) AND ..
.2. Я предполагаю, что это лучший способ написать это, но я думаю, что логика та же. Когда я добавил это в laravel: DB::raw(«book.visibility_school <> 1 ИЛИ schools.id = ‘?’ И schools.id <> 0» — опубликованные книги отображаются так, как должны, поэтому, возможно, laravel не понравился синтаксис, который я использовал. Но я не получаю книгу «visibility_school», когда я помещаю соответствующий идентификатор школы 3. Laravel, похоже, думает, что у этой книги есть идентификатор школы 0 (потому что он совпадает, когда я помещаю school.id = 0 (и удалите дополнительное предложение, которое я добавил «И schools.id <> 0»). В mysql запрос все же работает.
Ответ №1:
При использовании привязки параметров вам не нужно заключать кавычки вокруг вопросительного знака, так ?
и не '?'
.
DB::raw("IF(book.visibility_school = 1, IF(schools.id = ?, 1, 0), 1) = 1"),$currentUserSchoolId)
Однако, как предлагали другие, ваши проверки могут быть упрощены с помощью обычных операций и / или
Комментарии:
1. Если я удалю кавычки вокруг ? , я получу «SQLSTATE [HY093]: недопустимый номер параметра «. Я использую laravel 4.2, возможно, для этой версии требуется цитата (?)
Ответ №2:
Есть ли какая-либо причина, по которой вы не пользуетесь ORM, предоставляемым Laravel?
Со всеми отношениями, хорошо установленными в ваших моделях, вы должны получить более или менее похожий результат со следующим кодом:
MyController.php
$currentUserId = Auth::id();
$books = Book::with(['tag', 'rating', 'user', 'user.school' => function ($query) {
$query->selectRaw('name as schoolName')->addSelect('id');
}])
->whereHas('user', function ($query) use ($currentUserId) {
$query->where('id', $currentUserId);
})
->where('published', Book::STATUS_PUBLISHED)
->where('visibility_school', true)
->where('deleted', false)
->get();
}
Комментарии:
1. Я не хочу использовать его слишком часто для сложных запросов, потому что это медленнее. Запрос также должен возвращать все результаты book.visibility_school = 0, но если это 1, то школа автора книги должна соответствовать школе текущего пользователя.