6

How to implement BelongsToThrough Relationship in Laravel?

I have Table:

**projects_table**
id 

**categories_table**
id
project_id 

**properties_table**
id
category_id

Category BelongsTo Project

public function project(){
    return $this->belongsTo('App\Project');
}

Property BelongsTo Category

public function category(){
    return $this->belongsTo('App\Category');
}

How can we make a relationship?

Property BelongsTo Project Through Category

public function project(){
     return $this->belongsToThrough('App\Project', 'App\Category');
}

EDIT QUESTION.

Because I want to do multi-tenancy on my application, and the tenancy is PORJECT. I want to separate Category and Property by Project.

CATEGORY is belongsTo PROJECT PROPERTY is belongsTo CATEGORY

so I want to make relationship between PROPERTY and PROJECT via CATEGORY. for now, I need to add: project_id on both categories and properties tables and I think that this is not the right way.

Prafulla Kumar Sahu
  • 9,321
  • 11
  • 68
  • 105
Lim Socheat
  • 705
  • 2
  • 12
  • 25

4 Answers4

3

I think you can do $project->category->property as you have a one-to-one relationship between Project and Category and again a one-to-one relationship between Category and property, beside this, if you want to define a relationship between Project and Property through you may consider has-one-through relaationship.

In Project model

public function property()
{
    return $this->hasOneThrough('App\Property', 'App\Category');
}

and in Property model

public function property()
{
    return $this->hasOneThrough('App\Project', 'App\Category');
}

May be

In that case, you can also do something like

in Property model

public function project()
{    
   return $this->category->project( or projects);

   // or if Category and properties have many-to-many relationship you can do 
   return $this->categories->with('projects')->get();
}
Jhourlad Estrella
  • 3,545
  • 4
  • 37
  • 66
Prafulla Kumar Sahu
  • 9,321
  • 11
  • 68
  • 105
  • Thanks for your answer, but in this case, I cannot use hasOneThrough relationship. this is the error. SQLSTATE[42S22]: Column not found: 1054 Unknown column 'categories.property_id' in 'where clause' (SQL: select count(*) as aggregate from `properties` where exists (select * from `projects` inner join `categories` on `categories`.`id` = `projects`.`category_id` where `categories`.`deleted_at` is null and `properties`.`id` = `categories`.`property_id` and `id` = 1 and `categories`.`deleted_at` is null and `projects`.`deleted_at` is null) and `properties`.`deleted_at` is null) – Lim Socheat Sep 14 '19 at 08:28
  • Can you tell me, how Property and Category models are related? – Prafulla Kumar Sahu Sep 14 '19 at 08:41
  • `class Property extends Model { public function category() { return $this->belongsTo('App\Category'); } } class Category extends Model { public function project() { return $this->belongsTo('App\Project'); } }` – Lim Socheat Sep 14 '19 at 08:57
  • so I want to have Property Model to has a belongsTo Project Model via Category Model – Lim Socheat Sep 14 '19 at 08:59
  • @LimSocheat I am asking about foreign key only, let me know the foreign key that relates these two tables – Prafulla Kumar Sahu Sep 14 '19 at 09:00
  • please take a look this package, I want something like this: https://github.com/staudenmeir/belongs-to-through#usage `HasManyThrough` Project → has many → Category → has many → Property `BelongsToThrough` Property → belongs to → Category → belongs to → Project – Lim Socheat Sep 14 '19 at 09:12
  • Get this error. `message: "Trying to get property 'project' of non-object"` – Lim Socheat Sep 14 '19 at 09:39
  • all are belongsTo relationships. `Property` → belongsTo → `Category` → belongsTo → `Project` – Lim Socheat Sep 14 '19 at 09:40
  • then you are able to get `$property->cateory`, `$category->project`, `$category->property` and `$project->category` am I correct? – Prafulla Kumar Sahu Sep 14 '19 at 09:42
  • $categories->properties (hasMany), $project->categories (hasMany) – Lim Socheat Sep 14 '19 at 09:45
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/199459/discussion-between-prafulla-kumar-sahu-and-lim-socheat). – Prafulla Kumar Sahu Sep 14 '19 at 09:45
3

You want to use hasOneThrough with all keys specified like so

public function project()
    {
        return $this->hasOneThrough(
            Project::class,
            Category::class,
            'id', # foreign key on intermediary -- categories
            'id', # foreign key on target -- projects
            'category_id', # local key on this -- properties
            'project_id' # local key on intermediary -- categories
        );
    }
leevanoetz
  • 157
  • 1
  • 8
0

Your property belongsTo is incorrect. Property belongs to Category.

public function category(){
    return $this->belongsTo('App\Category','category_id');
}

Now you can get project from property like below:

{{ $property->category->project->project_attribute }} 
zahid hasan emon
  • 6,023
  • 3
  • 16
  • 28
  • Hi Zahid, I have updated my question! I want to build a multi-tenancy application. so I need to filter CATEGORY and PROPERTY by PROJECT. – Lim Socheat Sep 14 '19 at 08:36
  • you are getting what you want like this. what is the problem using like this?? what exactly you are trying to do?? – zahid hasan emon Sep 14 '19 at 09:07
0

You can't make it like this. If you want to access project Using properties. Then check this following steps which I mention as per your requirement.

Category.php Model

public function project(){
    return $this->belongsTo('App\Project','project_id','id');
}

Property.php model here you're doing wrong. You can access it directly you've to made relationship with categories first and from categories will get project.

Property BelongsTo Category

public function categories(){
    return $this->belongsTo('App\Category','category_id','id');
}

Now if you want to access it from controller then you may use with();

$property = Property::with('categories.project')->first();

Here you'll get $property->categories->project->name

Note: If you want to get property from the project then you can use hasOneThrough but inverse relation you can't make it.

Dilip Hirapara
  • 14,810
  • 3
  • 27
  • 49