Skip to content

[12.x] Add Eloquent Relationship Attributes #56415

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

Draft
wants to merge 3 commits into
base: 12.x
Choose a base branch
from

Conversation

WendellAdriel
Copy link
Contributor

Overview

Since Laravel has been embracing the usage of Attributes, this PR introduces 12 new attributes for defining relationships in the Eloquent Models.

Why

Right now, we use methods in Model classes to define relationships. But this can lead to a mix of methods like relationships, scopes, and mutators mixed inside the class. By using Attributes, we group all relationship definitions in one place in the class. This makes it easier to see all the relations for a model at once.

Examples

These attributes work just like methods. You pass the arguments in the same order. Here are some examples from the test cases in this PR.

#[BelongsTo(BookCase::class)]
#[HasMany(Price::class, null, 'custom_id', 'id')]
class Book extends Model {}

#[HasMany(Book::class)]
class BookCase extends Model {}

#[HasOne(Manufacturer::class)]
class Computer extends Model {}

#[HasMany(User::class)]
#[HasManyThrough(Post::class, User::class)]
class Country extends Model {}

#[MorphTo('imageable')]
class Image extends Model {}

#[HasMany(LibraryBook::class)]
class Library extends Model {}

#[BelongsTo(Library::class)]
class LibraryBook extends Book {}

class Manufacturer extends Model {}

#[BelongsTo(User::class)]
class Phone extends Model {}

#[BelongsTo(related: User::class, name: 'author')]
#[MorphMany(Image::class, 'imageable')]
#[MorphToMany(Tag::class, 'taggable')]
class Post extends Model {}

#[BelongsTo(Book::class, null, 'custom_id', 'id')]
class Price extends Model {}

#[BelongsToMany(User::class)]
class Role extends Model {}

#[HasOneThrough(Manufacturer::class, Computer::class)]
#[HasOne(Computer::class)]
class Seller extends Model {}

#[MorphedByMany(Post::class, 'taggable')]
class Tag extends Model {}

#[BelongsToMany(related: Role::class, name: 'roleList')]
#[HasMany(related: Post::class, name: 'articles')]
#[HasMany(WorkBook::class)]
#[HasOne(Phone::class)]
#[MorphOne(Image::class, 'imageable')]
class User extends Model {}

#[BelongsTo(User::class)]
final class WorkBook extends Book {}

@taylorotwell taylorotwell marked this pull request as draft July 25, 2025 14:46
@ludo237
Copy link

ludo237 commented Jul 25, 2025

This reminds me of Doctrine, which I don't know if it's good or bad 😅 this implementation assumes that the method is called like the relationship by default and use the $name property to overwrite it, right?

@WendellAdriel
Copy link
Contributor Author

This reminds me of Doctrine, which I don't know if it's good or bad 😅 this implementation assumes that the method is called like the relationship by default and use the $name property to overwrite it, right?

It assumes the conventional naming for the relationship, like between User and Post would be

$user->posts;
$post->user;

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.

2 participants