Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

mfoote's avatar

Self Relation on Model with date Constraint - Possible?

Laravel : 5.2 PHP: 5.6

I am trying to figure out how to ask this...

Is it possible to add a relation to self and then exclude anything newer than the current selection....

I am trying to determine if a call is unique by determining if a Call has Calls before the Current Call- I know crazy way to ask it heh... but basically this...

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;


class Call extends Model
{
    
    public function _previous_calls()
    {
        return $this->hasMany('App\Call', 'ani', 'ani')->where('start_time', '<', $this->start_time);
    }

}

it seems like $this->start_time is not valid because i am eager loading in my controller.

0 likes
7 replies
adamprickett's avatar

I'm not sure the issue is with $this->start_time - your hasMany() call references the same column as both local and foreign, therefore the relation should only ever match itself.

mfoote's avatar

@adamprickett ani is not a unique column in the table, id is the unique column. The relation above works if I remove the ->where('start_time', '<', $this->start_time). My issue is, I only want records previous to the current selection. I think this relation would be fine only loading a single record, but I am trying to do it in a query that pulls multiple calls.

It might help for you to see the controller....

public function details(Request $request)
    {
        $calls = Call::select(
            'start_time',
            'ani'
        )
            ->where('start_time', '>=', $request->input('start_date') . ' 00:00:00')
            ->where('start_time', '<=', $request->input('end_date') . ' 23:59:59')
            ->with([
                '_previous_calls' => function ($query) {
                },
                '_prospects' => function ($query) {
                    $query->select(['id', 'patient_id', 'phone', 'first_name', 'last_name', 'email']);
                    $query->with([
                        '_patients' => function ($query) {
                            $query->select(['id', 'patient_id']);
                            $query->with([
                                'appointments' => function ($query) {
                                    $query->select('id', 'patient_id', 'date', 'resource', 'status', 'canceled');
                                }
                            ]);
                        },
                        'secondary_patients' => function ($query) {
                            $query->with([
                                'appointments' => function ($query) {
                                    $query->select('id', 'patient_id');
                                }
                            ]);
                        }
                    ]);
                }
            ])
            ->get();

        return $calls;
    }
adamprickett's avatar

@mfoote Apologies, I hadn't realised that wasn't your key column.

I've just run the same in my current application and it's returned as expected.

What does $this->start_time return if you dd() in that method?

mfoote's avatar

@adamprickett it returns null, I think this is due to the fact I am doing this via the controller, $this is of a different scope in my situation, not a loaded model. I think i need to somehow limit it in the query inside...

->with([
     '_previous_calls' => function ($query) {
        //here
    },
tiagotavares's avatar

Hi @mfoote this is happening because your model doesn't have any data since you are using the Facade.

This ->where('start_time', '<', $this->start_time) needs to be moved from your relation into a scope.

E.g.

public function _previous_calls()
{
    return $this->hasMany('App\Call', 'ani', 'ani');
}

public function scopeHappeningBefore($query, $date) {
    return $query->where('start_time', '<', $date);
}

You can use this on your Controller like this, e.g.:

...
 '_previous_calls' => function ($query) use($date) {
    return $query->happeningBefore($date);
},
...

This will return you all the Calls before the received date.

Hope this is what you are looking for.

mfoote's avatar

@tiagotavares I dont have $date, it needs to come from the existing record. If I had the date, there would be no issue.

mfoote's avatar
mfoote
OP
Best Answer
Level 4

Closing this as no good answer.

Please or to participate in this conversation.