Structuring Laravel Model with Custom Accessor & Mutator
Tags: php, laravel, eloquent
Published: 2020-05-13 15:41:22

---
title: Structuring Laravel Model with Custom Accessor & Mutator
published: true
date: 2020-05-12 03:29:03 UTC
tags: php, laravel, eloquent
canonical_url: https://phpfour.com/structuring-laravel-model-accessor-mutator-getter-setter/
---

![Structuring Laravel Model with Custom Accessor & Mutator](https://phpfour.com/content/images/2020/05/laravel-model-accessor-1.png)

This article was originally published at: https://phpfour.com/structuring-laravel-model-accessor-mutator-getter-setter/

---

In a few recent projects, we have experimented with a slight alteration of Eloquent Models and have found some great value. I thought to share this in case someone else benefits the same way we did 🚀

Let’s first bring a **Product** model to life for an imaginary e-commerce store:

```
php artisan make:model Product

```

We now have our brand new Product model under App namespace:

```php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    // 
}

```

We do some initial setup at the beginning:

- Enforcing strict types
- Marking class as `final`
- Adding logical code sections

...resulting in this:

```php
<?php

declare(strict_types=1);

namespace App;

use Illuminate\Database\Eloquent\Model;

final class Product extends Model
{
    #-----------------------------------------------------------------
    # Class Constants
    #-----------------------------------------------------------------

    // 

    #-----------------------------------------------------------------
    # Class Properties
    #-----------------------------------------------------------------

    // 

    #-----------------------------------------------------------------
    # Relationships
    #-----------------------------------------------------------------

    //

    #-----------------------------------------------------------------
    # Accessors and Mutators
    #-----------------------------------------------------------------

    // 
}

```

Next we adhere to some general team conventions regarding table and primary key name and include the necessary relations:

```php
<?php

//

final class Product extends Model
{
    // 

    #-----------------------------------------------------------------
    # Properties
    #-----------------------------------------------------------------

    /**
     * @var string
     */
    protected $table = 'products';

    /**
     * @var string
     */
    protected $primaryKey = 'product_id';

    #-----------------------------------------------------------------
    # Relationships
    #-----------------------------------------------------------------

    /**
     * @return HasOne
     */
    public function currency(): HasOne
    {
        return $this->hasOne(Currency::class, 'currencyCode', 'currency');
    }

    // 
}

```

You may be wondering what’s new here, this is standard Laravel - you’re entirely correct. I’ve included these details to make sure someone new can also follow along 😌

At this stage we introduce our own style accessors and mutators to the model (also known as getters/setters):

```php
<?php

//

final class Product extends Model
{
    // 

    #-----------------------------------------------------------------
    # Accessors and Mutators
    #-----------------------------------------------------------------

    /**
     * @return string
     */
    public function getName(): string
    {
        return $this->getAttribute('name');
    }

    /**
     * @param string $name
     */
    public function setName(string $name): void
    {
        $this->setAttribute('name', $name);
    }

    /**
     * @return float|null
     */
    public function getPrice(): ?float
    {
        return $this->getAttribute('price');
    }

    /**
     * @param float|null $value
     */
    public function setPrice(?float $value): void
    {
        $this->setAttribute('price', $value);
    }

    /**
     * @return bool
     */
    public function isActive(): bool
    {
        return $this->getAttribute('is_active');
    }

    // 
}

```

That’s pretty straight-forward, but you may be wondering about the verbosity and why would someone write all these methods by hand.

### What's the benefit? 

Well, we have seen these benefit since introducing this overall structure:

- Model is divided into logical sections, so easy to navigate
- Model properties are available through IDE auto-completion
- Model properties are type-hinted, thus using the power of strict type
- It still preserves the power of Eloquent, so no hacky overrides

In our team we have seen overall improvement in DX (developer experience) as a result of these small changes. There are less errors, code comprehension has improved and cognitive load has reduced while working with someone else’s code.

### Why not just use the public properties? 

One question that comes up naturally when I present this to anyone: why not just use the public properties? Well, in my opinion there are a few limitations:   
  
  1. The data type of a given property cannot be enforced, you can set a float value to a property that is defined to store int in the DB  
  
  2. The return type of a given property cannot be determined, so on a language level you don't know if a status field is supposed to return string or int  
  
  3. Property level data validation is difficult, you can set a negative value to a property that is clearly invalid (ex: negative price of a product)  
  
  4. If a property column name is changed, that change needs to be done manually in all places where the property was accessed; as the properties are dynamic, thus cannot make use of IDE usage search

### Closing Thoughts

You may want to give this a try and see if this benefits in any way. This heavily favors the strong typing of PHP 7 so teams who has preference towards that would get the most out of this. And lastly, your mileage may vary 🙂

Share your ideas and thoughts with me in [Twitter](https://twitter.com/phpfour)!