Michael
Michael

Reputation: 576

Laravel 5.6 OneToOne relation not working

I have a BuildingImage model with a OneToOne relation to BuildingType:

BuildImage Model:

/**
 * Get the source type of the Building Image.
 */
public function type()
{
    return $this->hasOne('App\BuildingType');
}

BuildingType Model:

/**
 * Get the Building Image that owns the building type.
 */
public function buildingImage()
{
    return $this->belongsTo('App\BuildingImage');
}

My tables:

building_images table -> source is the building type id

source is the building type id

building_types table

enter image description here

When I try to do this in my controller just to test: (an ImageRequest has one or more Builings and a Building has one BuildingType)

$imageRequest = ImageRequest::findOrFail($id);

$buildings = $imageRequest->buildingImages;

foreach ($buildings as $building) {
    dd($building->type);
}

I get this error:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'building_types.building_image_id' in 'where clause' (SQL: select * from building_types where building_types.building_image_id = 45 and building_types.building_image_id is not null limit 1)

What am I doing wrong here?

Upvotes: 1

Views: 496

Answers (3)

Kenny Horna
Kenny Horna

Reputation: 14251

That's because by default laravel will look for a primary key named {model}_id, and given that you are using a different column name (source), you need to specify when defining the relationship:

As the documentation states:

Eloquent determines the foreign key of the relationship based on the model name. In this case, the Phone model is automatically assumed to have a user_id foreign key. If you wish to override this convention, you may pass a second argument to the hasOne method:

return $this->hasOne('App\Phone', 'foreign_key');

Additionally, Eloquent assumes that the foreign key should have a value matching the id (or the custom $primaryKey) column of the parent. In other words, Eloquent will look for the value of the user's id column in the user_id column of the Phone record. If you would like the relationship to use a value other than id, you may pass a third argument to the hasOne method specifying your custom key:

return $this->hasOne('App\Phone', 'foreign_key', 'local_key');

Now that that is clear. Let's talk about the relationship itself.

You are defining that a BuildImage has one BuildingType. But with that logic, the foreign key should be stored in the building_types table, and not the other way around (source column appears in the building_images table). And -I'm just assuming that- many BuildImage can belongs to an specific BuildingType. So, if this assumption is correct:

  • a BuildImage belongs to a specific BuildingType.
  • a BuildinType can be specify in many BuildImages

So, you should define your relationship like this:

BuildImage.php

public function type()
{
    return $this->belongsTo('App\BuildingType', 'source');
}

BuildingType.php

public function images()
{
    return $this->hasMany(BuildingImage::class, 'source');
}

Upvotes: 3

Bikash
Bikash

Reputation: 1938

Your BuildImage model should be

/** * Get the source type of the Building Image. */

public function type() {
    return $this->hasOne('App\BuildingType',"id","source"); 
}

And BuildingType Model should be

/** * Get the Building Image that owns the building type. */

public function buildingImage()
{
    return $this->belongsTo('App\BuildingImage',"source","id");
}

This should work. For more info have a look https://laravel.com/docs/5.7/eloquent-relationships#one-to-one

Upvotes: 1

Deimos
Deimos

Reputation: 269

Have you tried to indicate the index ID like this?

public function buildingImage()
{
    return $this->belongsTo('App\BuildingImage', 'image_request_id');
}

Eloquent determines the foreign key of the relationship based on the model name. In this case, the Phone model is automatically assumed to have a user_id foreign key. If you wish to override this convention, you may pass the second argument to the hasOne method:

return $this->hasOne('App\Phone', 'foreign_key');

https://laravel.com/docs/5.7/eloquent-relationships#one-to-one

Upvotes: 0

Related Questions