Skip to content
Advertisement

How to make Eloquent model attribute updatable only through public methods?

I want to prevent a model attribute from being directly set from an outside source without going through setters that control the logic.

class Person extends Model
{
    public function addMoney($amount)
    {
        if ($amount <= 0) {
            throw new Exception('Invalid amount');
        }
        $this->money += $amount;
    }

    public function useMoney($amount)
    {
        if ($amount > $this->money) {
            throw new Exception('Invalid funds');
        }
        $this->money -= $amount;
    }
}

This should not be allowed:

$person->money = -500;

You must use some kind of accessor or setter method:

$person->useMoney(100);

But I don’t care how you get the value:

echo $person->money;
// or
echo $person->getMoney();
// whatever

How do I enforce that the only way to update this attribute would be through specific methods that dictate some additional logic? In a sense, make a model attribute private or protected.

I want to do this separately and/or before the model data is persisted to the database.

Advertisement

Answer

You can override the set..Attribute() function for each member variable you want to protect, or you could potentially perform your validation inside the set..Attribute() function rather then having separate public methods.

class Person extends Model
{
    public function addMoney($amount)
    {
        if ($amount <= 0) {
            throw new Exception('Invalid amount');
        }

        if (!isset($this->attributes['money'])) {
            $this->attributes['money'] = $amount;
        } else {
            $this->attributes['money'] += $amount;
        }
    }

    public function useMoney($amount)
    {
        if ($amount > $this->money) {
            throw new Exception('Invalid funds');
        }

        if (!isset($this->attributes['money'])) {
            $this->attributes['money'] = -$amount;
        } else {
            $this->attributes['money'] -= $amount;
        }
    }

    public function setMoneyAttribute($val) {
        throw new Exception('Do not access ->money directly, See addMoney()');
    }

}
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement