在Laravel中,当orderBy()处理关系时如何合并where()和orderBy()?

时间:2019-09-05 18:49:17

标签: php laravel

我有两个模型,一个Track模型和一个Artist模型,其中每个Track模型belongsTo()一个Artist模型。 Track模型具有number列,而Artist模型具有name列。我想检索所有Tracks,其中number = 1,然后显示按其艺术家姓名排序的那些。到目前为止,我只想出了一种或另一种,而不是两者都做。

我希望能够通过以下方式做到这一点:

Track::with(['artist' => function($q) {
            $q->orderBy('name');
        }])->where('number', 1)->get();

这将显示number = 1tracks并未以任何特定顺序排序的所有曲目。如果完全删除with(),则得到相同的结果。相反,如果删除where()子句,则会在数据库中获得所有轨道,并按艺术家的名称对其进行排序。如何结合这两个功能?结果应如下所示:

[
  {
    "id": 17,
    "created_at": "2019-09-04 22:33:50",
    "updated_at": "2019-09-04 22:33:50",
    "number": 1,
    "title": "Iste omnis maxime inventore rerum nam et.",
    "artist_id": 2,
    "album_id": 4,
    "length": "06:08",
    "disc_number": 1,
    "artist": {
      "id": 2,
      "created_at": "2019-09-04 22:33:46",
      "updated_at": "2019-09-04 22:33:49",
      "name": "Ace",
      "image_id": "4"
    }
  },
  {
    "id": 35,
    "created_at": "2019-09-04 22:33:54",
    "updated_at": "2019-09-04 22:33:54",
    "number": 1,
    "title": "Doloremque quidem voluptatibus doloribus et.",
    "artist_id": 4,
    "album_id": 7,
    "length": "18:13",
    "disc_number": 3,
    "artist": {
      "id": 4,
      "created_at": "2019-09-04 22:33:46",
      "updated_at": "2019-09-04 22:33:53",
      "name": "Bar",
      "image_id": "10"
    }
  },
  {
    "id": 54,
    "created_at": "2019-09-04 23:00:08",
    "updated_at": "2019-09-04 23:00:08",
    "number": 1,
    "title": "Ut placeat assumenda aut.",
    "artist_id": 21,
    "album_id": 17,
    "length": "09:25",
    "disc_number": 4,
    "artist": {
      "id": 21,
      "created_at": "2019-09-04 23:00:08",
      "updated_at": "2019-09-04 23:00:08",
      "name": "Cat",
      "image_id": "22"
    }
  },
  {
    "id": 71,
    "created_at": "2019-09-04 23:00:11",
    "updated_at": "2019-09-04 23:00:11",
    "number": 1,
    "title": "Omnis et dolores odio a eius.",
    "artist_id": 22,
    "album_id": 20,
    "length": "16:48",
    "disc_number": 2,
    "artist": {
      "id": 22,
      "created_at": "2019-09-04 23:00:08",
      "updated_at": "2019-09-04 23:00:10",
      "name": "Dog",
      "image_id": "25"
    }
  },
]

2 个答案:

答案 0 :(得分:1)

使用类似这样的内容:

interface Base {
    someProp: { subProp: string; } | null;
    condProp1?: boolean;
    condProp2?: boolean;
}

interface WithProp1 extends Base {
    condProp1: true;
}

interface WithProp2 extends Base {
    condProp2: true;
}

export type MyType = WithProp1 | WithProp2;

我希望你明白我的意思

答案 1 :(得分:1)

您无法使用代码按歌手姓名排序,因为laravel要对eager load位有曲目的歌手执行两个查询,您应该使用join进行一个查询,但我提供了两个其他选项(我不喜欢加入):

1)您可以在结果https://stackoverflow.com/a/53631526/12001023上使用sortBy()sortByDesc()(如果要降序排列),例如:

$tracks = Track::with('artist')->where('number', 1)->get()->sortBy('artist.name');

2)您可以从Artist开始查询,但是您必须稍微改变一下看法,例如:

$artists = Artist::with(['tracks' => function($q) {
               $q->where('number', 1);
           }])->orderBy('name')->get();

3)您可以使用联接,请查看另一个答案。

仅供参考,如果您想调试查询,只需在->toSql()后面附加->get()即可获得SQL的字符串。