【问题标题】:Laravel Eloquent query siblings in same table with eager loadingLaravel Eloquent 查询同级表中的同级,并带有急切加载
【发布时间】:2022-01-25 08:01:09
【问题描述】:

我有一个名为patients 的父表,它与一个名为notes 的子表具有一对多的关系。 (即一名患者可以有多个笔记)。如果给出注释,我想为同一患者找到其他注释。注释通过名为patient_id 的fk 与患者相关。

在 SQL 中,我会这样做:

SELECT * FROM notes WHERE patient_id={note.patient_id} AND id <> {note.id}

在 Eloquent 中,我有这个:

class Note extends Model
{

    public function otherEncounterNotes()
    {
        return $this->hasMany('App\Note', 'patient_id', 'patient_id')->where('id', '<>',$this->id);
    }
...

在我的数据库中,id=1 的患者有两个 id 为 1 和 2 的笔记,所以如果我寻找笔记 id 1 的兄弟姐妹,我应该得到笔记 id 2。

当我使用find() 时,它按预期工作,但是当我使用where() 时,它返回原始注释而不是兄弟。有什么想法吗?

>>> Note::find(1)->otherEncounterNotes->pluck('id')                                                                                                                                                                             
=> Illuminate\Support\Collection {#5542
     all: [
       2,
     ],
   }

>>> Note::where('id',1)->with('otherEncounterNotes')->pluck('id')                                                                                                                                                               
=> Illuminate\Support\Collection {#5526
     all: [
       1,
     ],
   }

【问题讨论】:

  • find(1) 正在从数据库中返回模型,因此当调用关系方法时,otherEncounterNotes, ($this-&gt;id) 有一个值,因为该方法是在该实例上直接调用的,而您正在从返回的集合中提取...第二个是直接从表中提取 [不管任何关系](调用 with 急切加载关系对基本结果没有影响)
  • @lagbox - 有什么方法可以急切加载涉及 id 的逻辑?
  • 不,因为急切加载使用新的非现有模型从关系方法中获取构建器,它不会调用从具有属性的数据库中检索到的模型
  • 我能做的最好的就是Note::where('id',1)-&gt;get(['id','patient_id'])-&gt;each-&gt;append('otherEncounterNotes')

标签: php laravel eloquent siblings


【解决方案1】:

给定Note id,您可以通过使用与Patient 模型的关系来获得您想要的结果。

$note_id = 1;

// "Pretty" syntax, but it's 3 queries
$sibling_notes = Note::find($note_id)                                      // Query 1
                      ->patient                                            // Query 2
                      ->notes()->where('id', '<>', $note_id)->pluck('id'); // Query 3

或者使用子查询

$note_id = 1;

// A bit messier, 1 query + 1 subquery
$sibling_notes = Note::where('id', '<>', $note_id)
    ->where('patient_id', function ($subquery) use ($note_id) {
        $subquery->select('patient_id')->from('notes')->where('id', $note_id)->limit(1);
    })
    ->pluck('id');

// PHP >= 7.4
Note::where('id', '<>', $note_id)
    ->where('patient_id', fn($q) => $q->select('patient_id')->from('notes')->where('id', $note_id)->limit(1))
    ->pluck('id');

后者,你可以变成一个查询范围

# Note model
public function scopeSiblingsOf($query, $note_id)
{
    return $query->where('id', '<>', $note_id)
                 ->where('patient_id', function ($subquery) use ($note_id) {
                     $subquery->select('patient_id')
                              ->from('notes')
                              ->where('id', $note_id)
                              ->limit(1);
                 });
}

# Usage
Note::siblingsOf(1)->pluck('id');

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-17
    • 1970-01-01
    • 2021-10-02
    • 2017-10-09
    • 2014-06-12
    • 1970-01-01
    • 2014-11-07
    • 1970-01-01
    相关资源
    最近更新 更多