I have a table where I store different blocks of texts for my website. I am currently selecting the correct blocks for each page with the slug of the page, and the prefered language. I would like to select the same block of text (with the same title) in the fallback language when the prefered language is not available.
The blocks table
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
Required output
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
Currently I am only selecting the blocks with the selected prefered language, because I don't know how to approach this with selecting the 'fallback language' block if the 'prefered language' block is not available. I could try to run two queries for both languages, and then merge them somehow and only inserting the 'fallback language' blocks if the title count of this block is lower than 1, but this seems quite elaborate and not very elegant?
For my app I am using eloquent:
$blocks = Block::->where('slug', '=', 'home')
->whereIn('language', $selectedLanguage)
->get();
How could I do this in eloquent? (or in raw SQL, for that matter?)
You can use
GROUP_CONCAT
to do that.title
, to get all relevant strings in one row.GROUP_CONCAT
'sORDER BY
to put the desired language first.SUBSTRING_INDEX
to extract only the first string.Example query:
If i understand you correctly, you want to "remove" the rows with the fallback language if there is already a row with the prefered language for the same
slug
andtitle
.You can use a LEFT JOIN for the fallback language to check if an entry with the prefered language exists. For example if your preferd language is 'nl' and the fallback language is 'en' your query could look like:
sqlfiddle
The join in words could be somthing like: Look for a better translation for the same
slug
andtitle
. If the language is the prefered one there won't be a match because ofblocks.language <> 'nl'
. Otherwise the join will "search" for the prefered translation ('b1.language = 'nl'
).In the WHERE clause we tell only to return rows if no better translation has been found (
b1.id is null
).Best i could do to convert the query to eloquent is:
Note: I'm assuming that
title
is the same for a block in all languages. Otherwise you would need another column (likeblock_id
) to identify a block.