I am new to using PHP Frameworks. I decided to try out Laravel. In my project, I needed to write a search function which will search through a few entities based on some keywords, then do a UNION and return the results. So the SQL will look something like this:
SELECT pages.id,pages.updated_at,pages.created_at,page_translations.title,page_translations.description
FROM pages
INNER JOIN page_translations ON page_translations.page_id = pages.id
WHERE pages.deleted_at IS NULL
AND page_translations.deleted_at IS NULL
AND pages.published = 1
AND page_translations.locale = @lang
AND page_translations.active = 1
AND ( page_translations.title LIKE '%@keyword%'
OR page_translations.description LIKE '%@keyword%'
OR pages.id IN (
SELECT blockable_id
FROM blocks
WHERE blockable_type = 'App\\\\Models\\\\Pages'
AND content LIKE '%@keyword%'
)
)
UNION
SELECT articles.id,articles.updated_at,articles.created_at,article_translations.title,article_translations.description
FROM articles
INNER JOIN article_translations ON article_translations.article_id = articles.id
WHERE articles.deleted_at IS NULL
AND article_translations.deleted_at IS NULL
AND articles.published = 1
AND article_translations.locale = @lang
AND article_translations.active = 1
AND ( article_translations.title LIKE '%@keyword%'
OR article_translations.description LIKE '%@keyword%'
OR articles.id IN (
SELECT blockable_id
FROM blocks
WHERE blockable_type = 'App\\\\Models\\\\Articles'
AND content LIKE '%@keyword%'
)
)
ORDER BY updated_at DESC
I translated this query to use Laravel's Eloquent approach, and it looked something like this:
$pages = DB::table('pages')
->select(explode(',','pages.id,pages.updated_at,pages.created_at,page_translations.title,page_translations.description'))
->selectSub(function($query){
$query->selectRaw("'pages'");
},'content_type')
->join('page_translations','page_translations.page_id','=','pages.id')
->whereNull('pages.deleted_at')
->whereNull('page_translations.deleted_at')
->where([
['pages.published','=',1],
['page_translations.locale','=',$lang],
['page_translations.active','=',1],
])
->where(function($query) use ($keywords) {
$query->where('page_translations.title','LIKE','%'.$keywords.'%')
->orWhere('page_translations.description','LIKE','%'.$keywords.'%')
->orWhereIn('pages.id',function($subquery) use ($keywords) {
$subquery->select('blockable_id')
->from('blocks')
->where('blockable_type','=','App\\\\Models\\\\Page')
->where(function($blockquery) use ($keywords) {
$blockquery->where('content','LIKE','%'.$keywords.'%');
});
});
});
$articles = DB::table('articles')
->select(explode(',','articles.id,articles.updated_at,articles.created_at,article_translations.title,article_translations.description'))
->selectSub(function($query){
$query->selectRaw("'articles'");
},'content_type')
->join('article_translations','article_translations.article_id','=','articles.id')
->whereNull('articles.deleted_at')
->whereNull('article_translations.deleted_at')
->where([
['articles.published','=',1],
['article_translations.locale','=',$lang],
['article_translations.active','=',1],
])
->where(function($query) use ($keywords) {
$query->where('article_translations.title','LIKE','%'.$keywords.'%')
->orWhere('article_translations.description','LIKE','%'.$keywords.'%')
->orWhereIn('articles.id',function($subquery) use ($keywords) {
$subquery->select('blockable_id')
->from('blocks')
->where('blockable_type','=','App\\\\Models\\\\Article')
->where(function($blockquery) use ($keywords) {
$blockquery->where('content','LIKE','%'.$keywords.'%');
});
});
})
->union($pages)
->orderBy('content_type','desc')
->orderBy('updated_at','desc')
->get();
To me, the raw SQL approach is much more legible. And if my query had a few more subqueries, the SQL approach would still remain quite legible to me.
So my question is when developing with Laravel in a small team environment (2 other backend developers), is it best practice to never write Raw SQL? Is it the Laravel convention to always use Eloquent query builder methods unless there were exceptional circumstances such as bugs with eloquent, performance issues, etc...?