我有一个cms_contents
表,其中包含所有参展商(将其视为用户)和所有语言环境的内容。该表包含每个语言环境的默认内容,但是可以覆盖每个参展商的默认内容,并根据name
字段查询自己的版本。
一个简约的表格示例
| id | exhibitor_id | name | locale | content |
| --- | ------------ | -------------- | ------ | --------------------------- |
| 1 | NULL | privacy-policy | en | Default Privacy Policy ... |
| 2 | NULL | privacy-policy | nl | Standaard privacybeleid ... |
| 3 | 1 | privacy-policy | en | Custom Privacy Policy... |
我想创建一个函数来查询一个或多个记录,并仅按照以下规则按以下顺序返回正确的内容,并在第一个匹配项处停止
1.此name
和此locale
有自定义内容(exhibitor_id匹配)
2.此name
和此locale
有默认内容(exhibitor_id为空)
3.此name
有默认内容(exhibitor_id为null),并且locale
与后备区域设置匹配
4.其余的组合并不重要,这意味着我在db中输入了错误的数据。
这就是我现在所拥有的。
class CmsContent extends Model {
/**
* Returns a query builder with for fetching CmsContent with default content
*
* @param null $exhibitor_id
*
* @return static
*/
public static function withDefaultContent($exhibitor_id = null)
{
if (is_null($exhibitor_id)) {
$exhibitor_id = exhibitor()->id;
}
//TODO remove the need for database to not be in strict mode
return static
::where(function (Builder $query) {
return $query
->where('locale', app()->getLocale())
->orWhere('locale', config('app.fallback_locale'));
})
->where(function (Builder $query) use ($exhibitor_id) {
return $query
->where('exhibitor_id', $exhibitor_id)
->orWhereNull('exhibitor_id');
})
->orderByRaw('FIELD(`locale`, ?, ?)', [app()->getLocale(), config('app.fallback_locale')])
->orderBy('exhibitor_id', 'desc')
->groupBy(['name']);
}
}
用法示例
CmsContent::withDefaultContent()->where('name', 'privacy-policy')->first()
此功能的问题是GROUP BY不尊重ORDER BY。当我删除GROUP BY时,如果GROUP BY将采用每个组的第一个结果,则项目将正确排序。但事实并非如此。
第二个问题是它要求MySQL不要处于严格模式。
我该如何雄辩地解决这个问题?