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

fix attribute vs relation priorty #2577

Open
wants to merge 27 commits into
base: 4.1
Choose a base branch
from

Conversation

mshamaseen
Copy link

Attributes should be prioritized over relationship methods; this is how Laravel does it and what the developer anticipates.

The issue

The issue was (and I added a test for it), using this package, if you have a method name same as an attribute name, and you call the attribute, this package will return an error instead of returning the attribute.

for example:

/**
* @property string foo
*/
class model {
  function foo() {
    // this is not a relation, it is an action, do anything here
  }
}

Calling model->foo will throw an exception

The solution

This package was trying to call the method before the attribute because of embedded relations and (strangely) the many-to-many relation.

What I did in this PR is, Instead of calling the methods first, check if there is a method that has a return type of EmbedsOne or EmbedsMany and return it, otherwise continue using Laravel attribute/relation workflow (the same logic Laravel team applied for Attribute accessor functions).

For the BelongsToMany relation, I noticed that in the tests, the foreign key was called the same as the relation, let us say group.

So when $model->group was called, the tests expected the relation instead of the attribute, which is wrong, because attributes should be prioritized over relations.

The solution was so easy, just don't name the foreign key the same as the relation; that is the default behavior if you don't pass any foreign keys to $this->belongsToMany(related , /* Don't pass anything else */) , and that is also the documented way to do it.

Extra

While I was working I updated MySql/MongoDB versions in the dockerfile and github action file. I also dropped the support for mongoDB version 4 as starting from version 5 and above Mongosh is used instead of Mongo.

Follow laravel in the way that attributes are first then relation
…elease/v10

# Conflicts:
#	CHANGELOG.md
#	tests/Models/Group.php
#	tests/Models/MysqlGroup.php
#	tests/Models/MysqlUser.php
#	tests/Models/User.php
Copy link
Member

@GromNaN GromNaN left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for contributing your change back to the original project.

I think the changes you've suggested are useful, and will help us better stick to the way Eloquent works.

It needs to be review by @alcaeus and @divine.

src/Eloquent/Model.php Outdated Show resolved Hide resolved
src/Eloquent/Model.php Outdated Show resolved Hide resolved

### EmbedsMany Relationship

If you want to embed models, rather than referencing them, you can use the `embedsMany` relation. This relation is similar to the `hasMany` relation but embeds the models inside the parent object.

**REMEMBER**: These relations return Eloquent collections, they don't return query builder objects!

**Breaking changes** starting from v4.0 you need to define the return type of EmbedsOne and EmbedsMany relation for it to work
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I did in this PR is, Instead of calling the methods first, check if there is a method that has a return type of EmbedsOne or EmbedsMany and return it, otherwise continue using Laravel attribute/relation workflow (the same logic Laravel team applied for Attribute accessor functions).

Very smart. Can you please provide a link to where it's done like this in laravel.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.github/workflows/build-ci.yml Outdated Show resolved Hide resolved
@divine
Copy link
Contributor

divine commented Aug 26, 2023

Hello,

Any decision regarding embedded relations was made for v4.0 @GromNaN? I mean will be it rewritten completely or just "fixed" when a problem occurs?

We talked about it a lot and the way it currently "works" can lead to performance and logical problems.

My suggestion is that there should be a final decision made before v4.0 otherwise it can lead to Achilles's heel.

Thanks!

@GromNaN
Copy link
Member

GromNaN commented Aug 29, 2023

Hello,

Any decision regarding embedded relations was made for v4.0 @GromNaN? I mean will be it rewritten completely or just "fixed" when a problem occurs?

We talked about it a lot and the way it currently "works" can lead to performance and logical problems.

My suggestion is that there should be a final decision made before v4.0 otherwise it can lead to Achilles's heel.

Thanks!

To meet the need for a rapid release of a Laravel 10-compatible version, we won't be reworking the relationships for the time being.

@mshamaseen
Copy link
Author

@GromNaN any news about when this issue will be solved? your work is much appreciated!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants