I have a parent table called patients
which has a one-to-many relationship with a child table called notes
. (i.e. One patient can have several notes). If given a note, I would like to find other notes for the same patient. Notes are related to patients by a fk called patient_id
.
In SQL, I’d do this:
SELECT * FROM notes WHERE patient_id={note.patient_id} AND id <> {note.id}
In Eloquent, I have this:
class Note extends Model { public function otherEncounterNotes() { return $this->hasMany('AppNote', 'patient_id', 'patient_id')->where('id', '<>',$this->id); } ...
In my database, the patient with id=1 has two notes with ids 1 and 2, so if I look for the siblings of note id 1, I should get note id 2.
When I use find()
, it works as expected, but when I use where()
, it returns the original note instead of the sibling. Any ideas?
>>> Note::find(1)->otherEncounterNotes->pluck('id') => IlluminateSupportCollection {#5542 all: [ 2, ], } >>> Note::where('id',1)->with('otherEncounterNotes')->pluck('id') => IlluminateSupportCollection {#5526 all: [ 1, ], }
Advertisement
Answer
Given a Note
id, you could obtain the results you want by using the relationship with the Patient
model.
$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
Or using a subquery
$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');
The later, you could turn into a query scope
# 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');