Конструктор запросов Laravel: DB :: raw с оператором IF дает неверные результаты - PullRequest
1 голос
/ 03 апреля 2019

У меня есть запрос, который работает в 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 не возвращает никаких книг, за двумя исключениями:

  1. Если я установлю schools.id = 0, я получу 1 результат - одну книгу, видимую только учащимся определенной школы (номер 3).

  2. Если я установлю 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 (и удаляю AND schools.id <> 0), я тоже получу эту книгу - так что laravel считает, что идентификатор школы по какой-то причине равен 0. Так что это моя текущая проблема.

Ответы [ 2 ]

0 голосов
/ 03 апреля 2019

При использовании привязки параметров вам не нужно ставить кавычки вокруг знака вопроса, поэтому ?, а не '?'.

DB::raw("IF(book.visibility_school = 1, IF(schools.id = ?, 1, 0), 1) = 1"),$currentUserSchoolId)

Однако, как другие предложили, ваши проверки могут быть упрощены с помощьюнормальные и / или операции

0 голосов
/ 03 апреля 2019

Есть ли причина, по которой вы не пользуетесь 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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...