【问题标题】:Laravel eloquent, change query if no resultsLaravel 雄辩,如果没有结果则更改查询
【发布时间】:2014-11-27 09:39:58
【问题描述】:

制作一个多语言网站,并提供英语回退选项。

我有一个“语言”表

__________________
|language | text |
------------------
| "EN"  | "good" |
------------------
| "NL"  | "goed" |
------------------

我在控制器中的雄辩查询是:

Languages::language('EN')->take(1)->get(); 

在模型语言中,我有一个作用域函数:

public function scopeLanguage($query, $language)
{
    $query->where('language', '=', $language);
}

效果很好。但是当我尝试查询表中不存在的语言时。 例如:

Languages::language('DE')->take(1)->get(); 

它不返回任何结果,但我想回退到“EN”

我试过这样的事情:

public function scopeLanguage($query, $language)
{
    $query->where('language', '=', $language);
    if ($query->count() > 0) {
        return $query;
    } else {
        return $query->where('language', '=', "EN");
    }
}

没有运气,它似乎将新的 where 查询添加到现有查询中。 我可以删除/更改 where 查询吗?不断链(实际模型有多个作用域函数)

【问题讨论】:

  • 尝试在你的作用域函数中添加->get(),不执行我猜没有结果也没有计数
  • 在范围内进行操作意味着您将忽略稍后应用的其他wheres(或范围),因此不是这样。
  • 如果它在查询中添加where 条件,您可以将其替换为orWhere,它会正常工作。
  • @danny 你的意思是 $query->where('language', '=', $language)->get();?以及“不执行”是什么意思,顺便说一句,如果我在 else 中退出它,计数确实有效。感谢您的帮助
  • 你需要单行还是真的想要get那里?

标签: php laravel laravel-4 eloquent


【解决方案1】:

你也许可以试试:

public function scopeLanguage($query, $language)
{
    $q = clone $query;

    $q->where('language', '=', $language);
    if ($q->count() > 0) {
        return $query->where('language', '=', $language);
    } else {
        return $query->where('language', '=', "EN");
    }
}

由于它正在工作,它也可以简化一点

public function scopeLanguage($query, $language)
{
    $q = clone $query;

    $q->where('language', '=', $language);
    if ($q->count() == 0) {
        $language = 'EN';
    } 
    return $query->where('language', '=', $language);
}

【讨论】:

  • 同样导致 SQL:select * from languages where language = DE and language = EN limit 1
  • 你可以克隆 $query 但正如@JarekTkaczyk 提到的它可能无法解决问题
  • @77120 您的查询每次都不会返回任何内容。一个 `ield 不能同时有两个值。
  • 对象通过引用传递。
  • @JarekTkaczyk 你说得对,我已经添加了克隆,但我不知道它是否可以工作
【解决方案2】:

如果您不想破坏链条,可以在单独的查询中检查它:

public function scopeLanguage($query, $language){
  if(!self::where('language',$language)->count()){
    $language = 'EN';
  }
  return $query->whereLanguage($language);
}

【讨论】:

  • 这个解决方案有效,但我做了(有点偏颇)测试,比@MarcinNabiałek 解决方案慢很多。使用一个 4000 行的主表作为范围表和一个小表(作为语言表应该是)作为示例。平均时间:我的 - 0.048372030258179 / MarcinNabiałek 解决方案 - 1.0967254638672E-5
  • 检查查询,它们应该是一样的。
  • 很高兴知道,但可能一个测试不足以决定哪种方法更快,哪种方法更慢
  • 我有时间再做一次,@estshy 是对的,我(错误地)认为 'scopeLanguage' 是在不同的模型上(例如评论/帖子/等)。执行的查询完全相同。所以你的解决方案更易于维护,但我发现这个更干净。将其重构为更短。谢谢大家:)
  • 请记住,如果您有部分翻译,这些解决方案将失败。您打算重构代码尝试构建一个查询解决方案。
【解决方案3】:

MySQL 特定解决方案:

public function scopeLanguage($query, $language)
{
    $languages = [$language, 'EN'];

    $query->whereIn('language', $languages);

    $query->orderByRaw('field(language, ?, ?)', $languages);
}

然后调用first 而不是get

$query->language('DE')-> .... ->first();

【讨论】:

    【解决方案4】:
    public function scopeLanguage($query, $language)
    {
        $countQuery = clone $query;
        $countQuery->where('language', '=', $language);
    
        if ($countQuery->count() > 0) {
            return $query->where('language', '=', $language);
        } else {
            return $query->where('language', '=', "EN");
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-13
      • 2014-09-16
      • 1970-01-01
      • 2021-01-12
      • 1970-01-01
      • 1970-01-01
      • 2015-02-14
      • 1970-01-01
      相关资源
      最近更新 更多