我有一个在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
,则只包含某个学校ID的成员可以看到的额外书籍。
然而,laravel代码不返回任何书籍,但有两个例外:
schools.id = 0
,我得到1个结果,一本书只对某个学校的成员可见(应该是id 3)。schools.id = 1
- 我得到了5本出版的书籍。如果我设置任何其他ID,我得不到任何结果。如果我把$currentUserSchoolId
放在数组[$currentUserSchoolId]
中没有区别。 Book::STATUS_PUBLISHED
属性也等于1,因此那里的mysql代码版本没有区别。
因此,即使where if
不是1,laravel似乎也会将“visibility_school
”行评估为false。
---------更新---------
在提出建议之后,我改变了where if
线(并且还添加了:AND schools.id <> 0
):
->where(DB::raw("book.visibility_school <> 1 OR schools.id = '?' AND schools.id <> 0"),
$currentUserSchoolId)
现在我总是得到出版的书籍,所以这很好,但我仍然没有看到匹配的学校ID。如果我设置schools.id = 3
我应该得到它,它仍然可以在mysql中工作。但是如果我将它设置为0(并删除AND schools.id <> 0)我也会得到那本书 - 所以laravel认为学校ID因某种原因而为0。所以这是我目前的问题。
你有没有理由不利用the ORM provided by Laravel?
在relationships中设置了所有models,您应该使用以下代码获得或多或少相似的结果:
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();
}
使用参数绑定时,您不需要在问号周围传递引号,所以?
而不是'?'
。
DB::raw("IF(book.visibility_school = 1, IF(schools.id = ?, 1, 0), 1) = 1"),$currentUserSchoolId)
但是,正如其他人所建议的,您可以使用正常和/或操作简化检查