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

blackshtef's avatar

Retrieving data issue - relations problem

Hi everyone, so, I have several tables (I'll try to simplify):

  • reports (report_id, user_id, event_id, report_content)
  • hospitals (hospital_id, hospital_name)
  • events (event_id, user_id, hospital_id, event_date)
  • users (user_id, first_name, last_name)

The idea is that a user can create an event, and after the event is done, it will write a report on how the event went. The report has to show the date of the event and in which hospital the event took place. So far, I managed to get everything else within my model, but I'm having trouble retrieving the hospital name.

Here is the report model:

class Report extends Model
{
    use HasFactory;

    protected $fillable = [
        'report_id',
        'user_id',
        'event_id',
        'report_content',
        'report_status',
        'created_by',
        'created_at',
        'updated_at'
    ];

    protected $primaryKey = 'report_id';
    protected $table = 'reports'; 

    public function reportVolunteerInfo() {
        return $this->belongsTo('App\Models\User', 'user_id', 'user_id');
    }
    public function reportCreatedByInfo() {
        return $this->belongsTo('App\Models\User', 'created_by', 'user_id');
    }
    public function reportHospitalInfo() {
        return $this->belongsTo('App\Models\Hospital', 'hospital_id', 'event_id');
    }
    public function reportEventDate() {
        return $this->belongsTo('App\Models\Event', 'event_id', 'event_id');
    }
}

And if I try this in my blade template - it returns "Hospital name" {{$report->reportHospitalInfo->hospital_id ?? 'Hospital name'}}

Now, I am aware that hospital_id and event_id are not a match, but I'm not sure what would be wrong here since reportEventDate() also doesn't work.

Here are also models for Event and Hospital: Event:

class Event extends Model
{
    use HasFactory;

    protected $fillable = [
        'event_id',
        'user_id',
        'hospital_id',
        'report_id',
        'event_date',
        'event_content',
        'created_by'
    ];

    protected $primaryKey = 'event_id';
    protected $table = 'events'; //definiranje koju tablicu gledamo
}

Hospital:

class Hospital extends Model
{
    use HasFactory;

    protected $fillable = [
        'hospital_id',
        'full_hospital_name',
        'short_hospital_name',
        'hospital_color',
        'hospital_location',
        'hospital_coordinator',
        'hospital_max_people',
        'hospital_status'
    ];

    protected $primaryKey = 'hospital_id';
    protected $table = 'hospitals'; 
}
0 likes
33 replies
vincent15000's avatar

In the report model, are you sure of the owner key in this relationship ?

public function reportHospitalInfo() {
    return $this->belongsTo('App\Models\Hospital', 'hospital_id', 'event_id');
}

But your report model has no hospital_id attribute. Furthermore the third attribute should be the primary key of the model, in your case report_id.

Then it's normal that {{ $report->reportHospitalInfo->hospital_id ?? 'Hospital name' }} returns Hospital name because $report->reportHospitalInfo is probably null too.

So your relationship should look like this.

public function reportHospitalInfo() {
    return $this->belongsTo('App\Models\Hospital', 'hospital_id', 'report_id');
}
blackshtef's avatar

@vincent15000 I have added hospital_id attribute in the model, and tried the relationship as you said, but no changes. Is it enough to just add hospital_id in the model, without having that in the reports table? Becuase I didn't model the database like that, I figured that I would be able to get to the hospital name somehow through the event_id

1 like
vincent15000's avatar

@blackshtef No the foreign key has to be in the database too. After having added the hospital_id foreign key in the database, it should work if the hospital_id has a value for each report.

blackshtef's avatar

@vincent15000 No luck, I added the hospital_id column in the reports table, added it as well in the Report model, and filled out the values in the database, but I'm not getting the hospital name

1 like
vincent15000's avatar

@blackshtef Have you changed the relationship to this one ?

public function reportHospitalInfo() {
    return $this->belongsTo('App\Models\Hospital', 'hospital_id', 'report_id');
}
vincent15000's avatar

@blackshtef And you have the same mistake with another relationship.

public function reportEventDate() {
    return $this->belongsTo('App\Models\Event', 'event_id', 'report_id');
}

The third argument has to be the primary_key of the owner. Here an event belongs to the report, the report is the owner, and the primay key of the report is report_id.

vincent15000's avatar

@blackshtef

Can you replace ...

{{ $report->reportHospitalInfo->hospital_id ?? 'Hospital name' }}

by ...

{{ $report->reportHospitalInfo }}
// or
@dump($report->reportHospitalInfo)

And tell me what you see on the screen ?

blackshtef's avatar

@vincent15000 Also, I would argue that the event is the owner of everything - becuase the event has:

  • event_id (primary)
  • user_id (not null)
  • hospital_id (not null)
  • report_id (null, because a report can be filed days after the event) Not sure if that makes sense in this context, I just wanted to clarify my reasoning.
1 like
vincent15000's avatar

@blackshtef If the report_id of an event is null, you have no relation with the report, so from the report you cannot retieve the related models. Your problem is here.

The report has a primary key (for example 16), then 16 has to be the foreign key report_id in the event model to be able to retrieve the related event model via the relationship.

blackshtef's avatar

@vincent15000 with "non-dump" I get nothing, empty. The rest of the view render fine. If I do the dump one, I get syntax error, unexpected token "<"

<h4>{{$report->reportVolunteerInfo->first_name ?? 'Name'}} {{$report->reportVolunteerInfo->last_name ?? 'Last name'}} - {{ @dump($report->reportHospitalInfo) }}{{--$report->reportHospitalInfo->full_hospital_name ?? 'Hospital name'--}}
1 like
blackshtef's avatar

@vincent15000 But I inserted the values into the database, currently it has one event and one report, both have event_id and report_id set to "1". There are (for now) no null values anywhere. Both the event and the report have everything filled out, I did that to make sure that the relation should be there

1 like
vincent15000's avatar

@blackshtef I suggest you to add a report_id in the event models in the database. This will probably be the solution of at least a part of your problem ;).

vincent15000's avatar

@blackshtef Ok if you retrieve the only report in the database, you should be able to access the hospital name via the relationship. All seems to be ok with your code and your database.

Perhaps try this manually at the beginning of the controller method which displays the view.

$report = Report::find(1);
dd($report->reportHospitalInfo->full_hospital_name);

And tell me if you have the hospital name on the screen.

blackshtef's avatar

@vincent15000 Nope, this breaks everything:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'hospitals.report_id' in 'where clause'
select * from `hospitals` where `hospitals`.`report_id` = 1 limit 1
1 like
blackshtef's avatar

This is the Hospital model, if it helps:

    protected $fillable = [
        'hospital_id',
        'full_hospital_name',
        'short_hospital_name',
        'hospital_color',
        'hospital_location',
        'hospital_coordinator',
        'hospital_max_people',
        'hospital_status'
    ];
vincent15000's avatar

@blackshtef

@Sinnbeck please do you have time to have a look at his relationship ? ... for me it should work, but I suspect a problem with the explicit foreign key and/or primary key in the hospital relationship in the report model.

Sinnbeck's avatar

@blackshtef can you show how each model looks now after the updates, and the query that currently fails. I'm unsure what the current state is

blackshtef's avatar

@Sinnbeck sure: Hospital model:

class Hospital extends Model
{
    use HasFactory;
    protected $fillable = [
        'hospital_id',
        'full_hospital_name',
        'short_hospital_name',
        'hospital_color',
        'hospital_location',
        'hospital_coordinator',
        'hospital_max_people',
        'hospital_status'
    ];
    protected $primaryKey = 'hospital_id';
    protected $table = 'hospitals';
}

Events model:

class Event extends Model
{
    use HasFactory;
    protected $fillable = [
        'event_id',
        'user_id',
        'hospital_id',
        'report_id',
        'event_date',
        'event_content',
        'created_by'
    ];
    protected $primaryKey = 'event_id';
    protected $table = 'events'; 
}

Report model:

class Report extends Model
{
    use HasFactory;

    protected $fillable = [
        'report_id',
        'user_id',
        'event_id',
        'report_content',
        'report_status',
        'created_by',
        'created_at',
        'updated_at',
        'hospital_id'
    ];

    protected $primaryKey = 'report_id';

    protected $table = 'reports'; 
    public function reportVolunteerInfo() {
        return $this->belongsTo('App\Models\User', 'user_id', 'user_id');
    }
    public function reportCreatedByInfo() {
        return $this->belongsTo('App\Models\User', 'created_by', 'user_id');
    }
    public function reportHospitalInfo() {
        return $this->belongsTo('App\Models\Hospital', 'hospital_id', 'report_id');
    }
    public function reportEventDate() {
        return $this->belongsTo('App\Models\Event', 'event_id', 'report_id');
    }

Reports Controller (this works and returns reports):

$reports = Report::where('report_status', '=', '1') 
        ->select('user_id', 'created_by', 'created_at', 'report_content') 
        ->paginate(2); 
        return view('pages.reports', compact('reports'))->with(['page_title' => $page_title]);

Blade view:

<h4>
{{$report->reportVolunteerInfo->first_name ?? 'First name'}} //works
{{$report->reportVolunteerInfo->last_name ?? 'Last name'}} //works
{{$report->reportHospitalInfo->full_hospital_name ?? 'Hospital name'}} //doesn't work, returns "Hospital name"
{{$report->reportEventDate->event_date ?? 'Event date'}} //doesn't work, returns "Event date"
</h4>
Sinnbeck's avatar

Is this a preexisting database or is there some reason for not following laravel best practices? Tables should have a primary key named id. This should make relationships work without much effort

1 like
vincent15000's avatar

@Sinnbeck couldn't it work by specifying a custom primary key as third argument in the relationship as mentioned in the documentation ?

Sinnbeck's avatar

@vincent15000 absolutely, but it will make things a lot more predictable and way easier to read :)

1 like
blackshtef's avatar

@Sinnbeck It's a previous database. But yeah, I also wondered if that would be the issue - since I'm explicitly naming attributes I want to work with... I would rather find a solution that doesn't require changing the names of ID columns :)

1 like
Sinnbeck's avatar

@blackshtef ok fair enough. I've been there myself. I'll try and take another look at the Schema and requirements and see if I can help

1 like
blackshtef's avatar

@vincent15000 I haven't had the time to try out some ideas - will do that in the next couple of days and let you guys know if anything gave any results :)

1 like
blackshtef's avatar

@vincent15000 So, finally got the time to deal with this :) I did manage to solve my issue - all I had to do is to join two tables to my reports. I ended up not adding a hospital_id neither in the report model nor in the reports table.

So, instead of this in Reports Controller:

$reports = Report::where('report_status', '=', '1') 
        ->select('user_id', 'created_by', 'created_at', 'report_content') 
        ->paginate(2); 

I removed the select and added these two joins:

$reports = Report::where('report_status', '=', '1')
        ->join('events', 'reports.event_id', '=', 'events.event_id')
        ->join('hospitals', 'events.hospital_id', '=', 'hospitals.hospital_id')
		->paginate(2);

The Report model:

class Report extends Model
{
    use HasFactory;
    protected $fillable = [
        'report_id',
        'user_id',
        'event_id',
        'report_content',
        'report_status',
        'created_by',
        'created_at',
        'updated_at'
    ];
    protected $primaryKey = 'report_id';
    protected $table = 'reports'; 
	
public function reportVolunteerInfo() {
        return $this->belongsTo('App\Models\User', 'user_id', 'user_id');
    }

public function reportCreatedByInfo() {
        return $this->belongsTo('App\Models\User', 'created_by', 'user_id');
    }

 public function reportHospitalInfo() {
        return $this->belongsTo('App\Models\Hospital', 'hospital_id', 'hospital_id');
    }

Anyway, just wanted to let you guys know of the solution and to thank you for the assistance :)

1 like

Please or to participate in this conversation.