Using PHP Traits for Laravel Eloquent Relationships

Tom Ellis
3 min readSep 6, 2018

--

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.

--

--

Tom Ellis
Tom Ellis

Written by Tom Ellis

PHP and JavaScript hacker. Symfony and Laravel tinkerer. Open source developer.

Responses (11)