【问题标题】:How to merge hasMany relationships and return a relationship in Laravel?如何在 Laravel 中合并 hasMany 关系并返回一个关系?
【发布时间】:2018-06-15 04:29:10
【问题描述】:

我正在尝试合并 2 个集合,因为我需要在多个列中搜索记录,team_one_idteam_two_id,具体取决于它是客场比赛还是主场比赛。

这发生在函数matches 尝试合并它们时。当我在第一个关系上调用 merge 时,函数 matches 不会返回实际关系,而是返回一个集合。

例外:

SQLSTATE[21000]: Cardinality violation: 1222 The used SELECT statements have a different number of columns (SQL: (select count(*) as aggregate from `matches` where `matches`.`team_one_id` = 1 and `matches`.`team_one_id` is not null and `winning_team_id` = 1) union (select * from `matches` where `matches`.`team_two_id` = 1 and `matches`.`team_two_id` is not null))

代码:

<?php

namespace App\Database;

use Illuminate\Database\Eloquent\Model;

class Team extends Model
{
    protected $primaryKey = 'id';

    protected $table = 'teams';
    public $timestamps = false;
    protected $guarded = ['id'];

    public function homeMatches() {
        return $this->hasMany('App\Database\Match', 'team_one_id');
     }

     public function awayMatches() {
        return $this->hasMany('App\Database\Match', 'team_two_id');
     }

     public function matches() {
        return $this->homeMatches()->union($this->awayMatches()->toBase());
     }
}

【问题讨论】:

  • 搜索了你,没有看到任何使用 Eloquent 的方法。关系并非旨在匹配一个或另一个字段,它们旨在具有一个外键。但是,您没有理由不能设计一种方法来运行查询以返回匹配项。有什么理由让你没有选择它而不是专注于匹配是一种关系?
  • 我没有选择它,好像我做了类似return Match::where('team_one_id', $this-&gt;id)-&gt;orWhere('team_two_id', $this-&gt;id)-&gt;get(); 之类的事情,我在调用它后将无法查询它,除非我删除了-&gt;get() 并在每个实例上调用 get,还是我做错了?除非我在返回时删除-&gt;get(),否则我似乎无法在其上调用orderBy之类的东西。
  • 是的,没错,因为 get() 运行查询并返回一个集合,所以它不再可查询。
  • 我想我只是对不断调用get() 部分的强迫症。我会选择你的建议。

标签: php laravel


【解决方案1】:

Eloquent 关系并非旨在匹配一个或另一个字段,它们旨在具有一个外键。您可以在您的方法中运行查询以获得所需的结果,而无需依赖关系。

如 cmets 中所述,如果您想重复使用该查询,请将该逻辑包含在受保护的函数中。

 protected function allMatchesQuery()
 {
     // This needs to be wrapped in a nested query or else your orWhere will not be contained in parentheses.
     return Match::where(function($q) { 
          $q->where('team_one_id', $this->id)->orWhere('team_two_id', $this->id);
     });
 }

 public function getMatches() {
    return $this->allMatchesQuery()->get();
 }


 public function getRecentMatches() {
    return $this->allMatchesQuery()->orderBy('date', 'DESC')->limit(10)->get();
 }

【讨论】:

    【解决方案2】:

    你可以试试这个:

     public function matches() {
        return $this->getRelationValue('homeMatches')->union($this->getRelationValue('awayMatches')->toBase());
     }
    

    因为 homeMatches() 函数返回一个 Relation 实例,但动态属性返回一个 Collection。

    【讨论】:

    • 这会抛出Method Illuminate\Support\Collection::getBindings does not exist.,所以我认为它不会像你想象的那样。
    • "homeMatches""awayMatches" 更改为 getRelationValue('homeMatches')getRelationValue('awayMatches')
    • 我认为这个回复解决了你的问题。因为我目前在一个示例 laravel 项目上对其进行了测试。您关于动态属性的异常消息,所以我将此回复更改为 getRelationValue()
    猜你喜欢
    • 1970-01-01
    • 2015-11-22
    • 1970-01-01
    • 2017-11-15
    • 2019-12-15
    • 2014-12-22
    • 2021-11-06
    • 2020-01-18
    相关资源
    最近更新 更多