Laravel:急切加载数据透视表并在数据透视表字段上排序

时间:2014-02-26 20:00:47

标签: php mysql laravel-4 eloquent

我有一个国家/地区表和一个数据透视表Country_language,其中列出了所有国家/地区的翻译版本。

表结构如下:

Languages
--------------
ID
Locale

Records :
1 - EN
2 - FR

Countries
------------
ID
code

Records: 
1 - BE
2 - US

Country_language
-----------------------
ID
country_id
language_id
name

Records :

1 - 1 - 1 - Belgium

2 - 1 - 2 - Belgique

3 - 2 - 1 - United States

4 - 2 - 3 - Les États-Unis

在我的国家/地区模型中,我与语言数据透视表有如下关系:

public function translation()
{
    return $this->belongsToMany('Language', 'country_language', 'country_id','language_id')->withPivot('name');

}

现在我想得到一个给定语言的所有国家的列表,这应该按名称DESC进行排序。

我使用以下代码执行此操作:

$countries = Country::with(array('translation' => function($query) {
        $query->where('language_id', '=', 1); // fetch countries in English
        $query->orderBy('name', 'desc'); 
 }))->get();  

如果我打印$ countries但是我得到以下列表,其顺序不正确。我希望它首先给“美国”,然后给“比利时”。

[
    {
    "id": 1,
    "code": "BE",
    "translation": 
    [{
        "id": 1,
        "locale": "EN",
        "pivot": 
        {
            "country_id": 1,
            "language_id": 1,
            "name": "Belgium"
        }
    }]
    },
   {
   "id": 2,
   "code": "US",
   "translation": 
   [{
       "id": 2,
       "locale": "EN",
       "pivot": 
       {
           "country_id": 2,
           "language_id": 1,
           "name": "United States"
       }
   }]
   }
]

如果我检查正在运行的查询,它看起来如下:

 select `languages`.*, `country_language`.`country_id` as `pivot_country_id`, `country_language`.`language_id` as `pivot_language_id`, 
`country_language`.`name` as `pivot_name` from `languages` 
inner join `country_language` on `languages`.`id` = `country_language`.`language_id` 
where `country_language`.`country_id` in (?, ?) and `language_id` = ? order by `name` desc

哪个是正确的,如果我在MySQL中运行,我会按名称顺序降序获取国家/地区列表。

我在这里做错了什么,或者这可能是Laravel的一个问题? 感谢您抽出宝贵时间回答。

编辑: 基本上我只想在Eloquent中进行以下查询..看起来很简单,但显然很难(如果可能的话)在Eloquent中完成:

select country_language.*, languages.* 
from country_language
join countries on countries.id = country_language.country_id
join languages on languages.id = country_language.language_id
where country_language.language_id = 1
order by country_language.name desc

1 个答案:

答案 0 :(得分:0)

您正在使用急切的加载限制。 这不会影响外部查询的结果 - 它只限制和排序相关记录。如果你愿意,例如检索$ countries-> first() - >翻译 - >那些是按名称排序的。

在您的情况下,即使country_language表中没有记录,您也会收到所有国家/地区。因为您的限制仅适用于相关记录。

如果您只想在country_language表中拥有相关记录的国家/地区,则应使用whereHas。这可能会导致类似:

$countries = Country::with(array('translation' => function($query) {
    $query->where('language_id', '=', 1); // fetch only country_language records with language_id = 1
  }))->whereHas('translation', function($query) {
     $query->where('language_id', '=', 1); // fetch countries in English
    $query->orderBy('name', 'desc'); 
 ->get(); 

请检查这是否会以正确的方式订购您的结果。我可以想象orderBy必须链接在原始国家集合上,因此在内部函数中

那应该是这样的:

$countries = Country::with(array('translation' => function($query) {
    $query->where('language_id', '=', 1); // fetch only country_language records with language_id = 1
  }))->whereHas('translation', function($query) {
     $query->where('language_id', '=', 1); // fetch countries in English
 ->orderBy('name', 'desc');
 ->get(); 

在这种情况下,我不确定您是否可以在name列上订购。也许它不可访问,那么你可能需要使用join语句。