【问题标题】:How to execute/return a part of a query based on a result of that query (with Eloquent, or raw SQL)?如何根据查询的结果(使用 Eloquent 或原始 SQL)执行/返回查询的一部分?
【发布时间】:2016-09-04 13:33:55
【问题描述】:

我正在尝试根据页面的 slug(标识符)和设置的区域设置/语言来获取页面的内容。但是,如果该页面在具有所选语言环境的数据库中不可用,我想返回具有后备语言环境的页面,该页面应该始终可用(如果不可用,则返回错误)。

对于我的应用,我使用 Laravel 的 Eloquent ORM。

“pages”表中的数据(伪代码):

- entry 1:
    title: About
    slug: about
    locale: en
    content: the content of the about page

- entry 2:
    title: Informatie
    slug: about
    locale: nl
    content: De tekst van de informatie pagina

- entry 3:
    title: Home
    slug: home
    locale: en
    content: The content of the home page

所需的输出(使用后备语言环境 = en):

Required return to set $page to:

if the selected locale = nl, slug = about:
     'entry 2'
if the selected locale = en, slug = about:
     'entry 1'
if the selected locale = nl, slug = home:
     (since the nl-page is not available for this slug)
     set $page to 'entry 3'

这是我写的代码:

<?php
... other code ...

//based on selection
$slug = 'something';
$locale = 'the selected locale';

//setting for fallback Locale
$fallbackLocale = 'en';

//first try to get the page with the selected locale        
$page = Page::where([
                    'slug' => $slug,
                    'locale' => $locale
                ])
                ->first();

// if the first query is empty, get the page with the fallback Locale
if (empty($page))
{
    $page = Page::where([
                        'slug' => $slug,
                        'locale' => $fallbackLocale
                    ])
                    ->firstOrFail();
}

如您所见,尽管我执行了两个查询,但这段代码确实有效。我想执行一个查询,它检查查询的前半部分是否返回某些内容(具有所选语言环境的页面),如果这是空的,则查找具有后备语言环境的页面(slug 仍然是相同的)。

有没有办法用 Eloquent 做到这一点?(我不这么认为,在 eloquent 中带有 'if' 语句的方法旨在用于检查是否设置了表单中的参数,而不是查询是否返回)

如果使用 Eloquent 无法实现,那么仅使用常规 SQL 是否可行?

【问题讨论】:

  • 样本数据和期望的结果确实有助于传达您想要做的事情。
  • 你怎么知道一个查询会更快?现在有多慢?它会影响性能吗?你量过吗?您使用一个查询对您的数据进行了测试?它更快吗? imo,你需要测量它。如果没有测量,那么您如何决定哪个更好或更差?没有证据表明一个查询总是或经常优于两个查询。为什么?第一个查询将内容加载到内存中......
  • 好吧,我不知道如何用一个查询来做到这一点,所以我无法用一个查询来衡量它。我认为通常只执行一个查询比执行多个查询更好,因为只需要建立一个连接(尽管多个较小的查询可能比一个大的查询更快)。

标签: php mysql sql eloquent


【解决方案1】:

如果您同时选择两者并按locale = 'en' 订购,将首先选择“nl”,因为'nl' = 'en'0'en' = 'en'1

$page = Page::where('slug', $slug)
    ->whereIn('locale', [$locale, $fallbackLocale])
    ->orderByRaw("locale = '$fallbackLocale'")
    ->first();

这里的问题:如果$fallbackLocale来自用户输入,则不是注入保存。而且我没有找到在orderByRaw() caluse 中使用占位符的方法。

但您可以使用带有占位符的原始查询:

$page = Page::hydrateRaw("
        select *
        from pages
        where slug = ?
          and locale in (?, ?)
        order by locale = ?
        limit 1
    ",
    [$slug, $locale, $fallbackLocale, $fallbackLocale]
)->first();

更新:

我找到了在orderByRaw() 中使用占位符的方法:

$page = Page::where('slug', $slug)
    ->whereIn('locale', [$locale, $fallbackLocale])
    ->orderByRaw("locale = ?")
    ->addBinding($fallbackLocale, 'order')
    ->first();

【讨论】:

  • 我很喜欢你的思维方式。尽管当我实施第一种方法时,它给了我一个错误,它不知道“en”列:SQLSTATE [42S22]:找不到列:1054 Unknown column 'en' in 'order Clause'(SQL:select * from @ 987654332@ 其中slug = home 和locale in (nl, en) order by locale = en)
  • @FeatherNL - 修复了这个问题。但是你不应该直接使用第一个解决方案,除非你找到了使用占位符的方法。
猜你喜欢
  • 2017-11-14
  • 1970-01-01
  • 1970-01-01
  • 2021-05-21
  • 2015-01-08
  • 1970-01-01
  • 2018-12-31
  • 2017-09-10
  • 2019-11-18
相关资源
最近更新 更多