Skip to main content

Using PHP Traits for Laravel Eloquent Relationships

 

Traits for Laravel Eloquent Relationships

I recently began refactoring a bunch of code on a project and found myself putting the same methods on my Eloquent models for a relation to an Account class. 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:

<?php

namespace
App;
use Illuminate\Database\Eloquent\Model;/**
* 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 \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
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 Traits

I’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:

<?php

namespace
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 \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
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:

<?php

namespace
App;
use Illuminate\Database\Eloquent\Model;/**
* 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;
}
}

Conclusion

Using 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.

Comments

Popular posts from this blog

Laravel: The hidden SetCacheHeaders Middleware

There are a lot of useful middlewares already registered inside Laravel, like the   authentication mechanisms ,   authorization , a   throttler , and even the one responsible to make   route model binding   possible. Practically, your middleware needs are covered. Except for one. There is one middleware that doesn’t get the spotlight in Laravel. It’s called   SetCacheHeaders , which is aliased as   cache.headers . And, there is no mention of it in the documentation. I’m not joking, guys: Who, when, how? A quick look around in the   api documentation   and the   source repository   says this middleware was added   added before christmas of 2017   after   a lengthy discussion , but it's a mystery why nobody has talked about it since it’s seems very…   convenient . In any case, after making this article, my   PR to the documentation   was accepted, so   you should find it now in the documentation . A ...