Using PHP Traits for Laravel Eloquent Relationships

FYI I prefer to have getters and setters rather than accessing properties magically.So lets say we have a Post model that looks something like this:<?phpnamespace App;use IlluminateDatabaseEloquentModel;/** * Class Post * * @package App */class Post extends Model{ /** * @return string */ public function getTitle() { return $this->getAttribute('title'); } /** * @param string $title * @return $this */ public function setTitle(string $title) { $this->setAttribute('title', $title); return $this; } /** * @return string */ public function getPost() { return $this->getAttribute('post'); } /** * @param string $post * @return $this */ public function setPost(string $post) { $this->setAttribute('post', $post); return $this; } /** * @param Account $account * @return $this */ public function setAccount(Account $account) { $this->account()->associate($account); return $this; } /** * @return Account|null; */ public function getAccount() { return $this->getAttribute('account'); } /** * @return IlluminateDatabaseEloquentRelationsBelongsTo */ public function account() { return $this->belongsTo(Account::class, 'account_id', 'id'); }}We have some methods defined for the Post properties and then some for the Account relation.Now when we add another model that has a relationship to an Account we’d have to add the same methods..This can be time consuming, and if you ever wanted to change the methods you would have to do it on all models that have that relationship.Enter TraitsI’ll start with Php.net definition:Traits are a mechanism for code reuse in single inheritance languages such as PHP..A Trait is intended to reduce some limitations of single inheritance by enabling a developer to reuse sets of methods freely in several independent classes living in different class hierarchies..The semantics of the combination of Traits and classes is defined in a way which reduces complexity, and avoids the typical problems associated with multiple inheritance and Mixins.A Trait is similar to a class, but only intended to group functionality in a fine-grained and consistent way..It is not possible to instantiate a Trait on its own..It is an addition to traditional inheritance and enables horizontal composition of behavior; that is, the application of class members without requiring inheritance.This is the perfect reason for using traits..We’ll create a trait called HasAccountTrait which will hold all the methods for a relation belonging to an account:<?phpnamespace App;/** * Class HasAccountTrait * * @package App */trait HasAccountTrait{ /** * @param Account $account * @return $this */ public function setAccount(Account $account) { $this->account()->associate($account); return $this; } /** * @return Account|null; */ public function getAccount() { return $this->getAttribute('account'); } /** * @return IlluminateDatabaseEloquentRelationsBelongsTo */ public function account() { return $this->belongsTo(Account::class, 'account_id', 'id'); }}We can then tidy up our Post model from above to use this Trait, so it would look something like this:<?phpnamespace App;use IlluminateDatabaseEloquentModel;/** * Class Post * * @package App */class Post extends Model{ use HasAccountTrait; /** * @return string */ public function getTitle() { return $this->getAttribute('title'); } /** * @param string $title * @return $this */ public function setTitle(string $title) { $this->setAttribute('title', $title); return $this; } /** * @return string */ public function getPost() { return $this->getAttribute('post'); } /** * @param string $post * @return $this */ public function setPost(string $post) { $this->setAttribute('post', $post); return $this; }}ConclusionUsing traits means we can create DRY code when defining relationships to the same source..It could also speed up development, depending on how many relationships exist in your application.. More details

Leave a Reply