Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhanced Syntax and Behavior for hasOneThrough and hasManyThrough Relationships in Laravel's Eloquent ORM #641

Open
rajubeparybd opened this issue Jun 13, 2023 · 4 comments
Labels
enhancement New feature or request

Comments

@rajubeparybd
Copy link

rajubeparybd commented Jun 13, 2023

Synopsis:

The hasOneThrough and hasManyThrough relationships in Laravel's Eloquent ORM allow you to define indirect associations between models by going through intermediate models. These relationships are useful when you have a chain of relationships and want to access related models through that chain.

Proposed Syntax:

Yaml would use the following syntax:

hasOneThrough:
  - model: TargetModel
  - through: IntermediateModel
  
hasManyThrough:
  - model: TargetModel
  - through: IntermediateModel

To define a hasOneThrough relationship, you would use the following syntax:

public function targetModel()
{
    return $this->hasOneThrough(TargetModel::class, IntermediateModel::class);
}

To define a hasManyThrough relationship, you would use the following syntax:

public function targetModels()
{
    return $this->hasManyThrough(TargetModel::class, IntermediateModel::class);
}

Expected Behavior:

When you define a hasOneThrough or hasManyThrough relationship, Laravel will automatically generate the necessary SQL queries to retrieve the related models through the intermediate model.

For example, if you have the following models: User, Role, and Permission, and you want to define a hasOneThrough relationship between User and Permission through the Role model, you would use the following code:

class User extends Model
{
    public function permission()
    {
        return $this->hasOneThrough(Permission::class, Role::class);
    }
}

Now, you can access the Permission model associated with a User instance using the permission dynamic property:

$user = User::find(1);
$permission = $user->permission; // Retrieves the permission associated with the user

Similarly, if you want to define a hasManyThrough relationship, you would use the same syntax, but the relationship method would return a collection of related models:

class User extends Model
{
    public function permissions()
    {
        return $this->hasManyThrough(Permission::class, Role::class);
    }
}

Now, you can access the collection of Permission models associated with a User instance using the permissions dynamic property:

$user = User::find(1);
$permissions = $user->permissions; // Retrieves the collection of permissions associated with the user
@rajubeparybd rajubeparybd added enhancement New feature or request pending This issue is pending review labels Jun 13, 2023
@jasonmccreary
Copy link
Collaborator

I am glad to support the has*Through relationships. I don't like the proposed syntax. I'd like something a little more streamlined, such as:

hasOneThrough: TargetModel:IntermediateModel, AnotherModel:AnotherIntermediateModel

This way it is like the other relationships.

@rajubeparybd
Copy link
Author

There should be a way to pass the local and foreign keys for those tables. The foreign key should be optional. Follow Laravel Docs

The syntax when the Foreign key is set:

hasOneThrough: TargetMode.foreignKey:IntermediateModel.foreignKey, AnotherModel.foreignKey:AnotherIntermediateModel.foreignKey

The syntax when the Foreign key is not set:

hasOneThrough: TargetModel:IntermediateModel, AnotherModel:AnotherIntermediateModel

@impeto
Copy link

impeto commented Nov 21, 2023

If we follow the Laravel docs, we can have something like this:

Project:
  relationships:
    hasManyThrough: Deployment, Environment, project_id, environment_id, id, id

With the foreign and local keys optional.

@jasonmccreary
Copy link
Collaborator

Again, I am open to this. But it needs to be more streamlined.

@jasonmccreary jasonmccreary added the in progress This issue is being worked on. label Mar 6, 2024
@jasonmccreary jasonmccreary removed pending This issue is pending review in progress This issue is being worked on. labels Dec 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants