我有一张桌子,可以为我的网站存储不同的文本块。我目前正在为页面的slug和首选语言为每个页面选择正确的块。当首选语言不可用时,我想在后备语言中选择相同的文本块(具有相同的标题)。
阻止表
columns:
| id | slug | title | language | content |
entries:
| 1 | home | first | en | the first block |
| 2 | home | first | nl | het eerste blok |
| 3 | home | second | en | the second block |
--> block "second" not available for the 'nl' language
必需输出
fallback language = en
selected prefered language = en, output:
| 1 | home | first | en | the first block |
| 3 | home | second | en | the second block |
selected prefered language = nl, output:
| 2 | home | first | nl | het eerste blok |
| 3 | home | second | en | the second block |
--> select this one, because the 'nl' version is not available
目前我只选择具有所选首选语言的块,因为如果“首选语言”块不可用,我不知道如何通过选择“后备语言”块来解决这个问题。我可以尝试为这两种语言运行两个查询,然后以某种方式合并它们,如果此块的标题计数低于1,则只插入“后备语言”块,但这看起来相当复杂而且不是很优雅?
对于我的应用程序,我使用雄辩:
$blocks = Block::->where('slug', '=', 'home')
->whereIn('language', $selectedLanguage)
->get();
我怎么能在雄辩中这样做? (或者在原始SQL中,就此而言?)
答案 0 :(得分:2)
如果我理解正确,您希望使用后备语言“删除”行,如果已有一行包含相同slug
和title
的首选语言。
您可以使用LEFT JOIN作为后备语言来检查是否存在具有首选语言的条目。例如,如果您喜欢的语言为'nl'且后备语言为'en',则您的查询可能如下所示:
select blocks.*
from blocks
left join blocks b1
on b1.slug = blocks.slug
and b1.title = blocks.title
and b1.language = 'nl'
and blocks.language <> 'nl'
where blocks.slug = 'home'
and blocks.language in ('nl', 'en')
and b1.id is null
单词中的联接可能类似于:为同一slug
和title
寻找更好的翻译。如果语言是首选语言,则由于blocks.language <> 'nl'
而不会匹配。否则,联接将“搜索”首选翻译('b1.language = 'nl'
)。
在WHERE子句中,如果找不到更好的翻译,我们只会返回行(b1.id is null
)。
我能将查询转换为eloquent的最佳方法是:
$prefered = 'nl';
$fallback = 'en';
$blocks = App\Block::where('blocks.slug', '=', 'home')
->whereIn('blocks.language', [$prefered, $fallback])
->leftJoin('blocks as b1', function($join) {
$join->on('b1.slug', '=', 'blocks.slug')
->on('b1.title', '=', 'blocks.title')
->on('b1.language', '=', DB::raw('?'))
->on('blocks.language', '<>', DB::raw('?'))
;
})
->whereNull('b1.id')
->addBinding([$prefered, $prefered], 'join')
->select(DB::raw('blocks.*'))
->get()
;
注意:我假设title
对于所有语言的块都是相同的。否则,您需要另一列(如block_id
)来标识块。
答案 1 :(得分:1)
您可以使用GROUP_CONCAT
来执行此操作。
title
分组,以获取一行中的所有相关字符串。GROUP_CONCAT
的{{1}}将所需语言放在首位。ORDER BY
仅提取第一个字符串。示例查询:
SUBSTRING_INDEX