Laravel ignore mutators
Asked Answered
C

8

12

I am using Laravel's Mutator functionality and I have the following Mutator:

public function setFirstNameAttribute($value)
{
    $this->attributes['first_name'] = strtolower($value);
}

However I need to Ignore this Mutator in some cases. Is there any way to achieve this

Cawley answered 8/5, 2017 at 7:10 Comment(1)
If this functionality isn't always needed, surely it should be moved to the functionality where it is needed and remove the mutator?!Vingtetun
E
22

Set a public variable in model, e.g $preventAttrSet

public $preventAttrSet = false;

public function setFirstNameAttribute($value) {
    if ($this->preventAttrSet) {
        // Ignore Mutator
        $this->attributes['first_name'] = $value;
    } else {
        $this->attributes['first_name'] = strtolower($value);
    }
}

Now you can set the public variable to true when want to Ignore Mutator according to your cases

$user = new User;
$user->preventAttrSet = true;
$user->first_name = 'Sally';
echo $user->first_name;
Endurant answered 8/5, 2017 at 13:49 Comment(2)
This doesn't work with query builder somehow, it reset to first state :(Featherbrain
never mind it works now linkFeatherbrain
S
20

Whereas the answers provided seems to work, there is a method in Laravel to access the original value:

$service->getOriginal('amount')

See this post: Example of getOriginal()

Api: API Documentation

Smoky answered 16/8, 2017 at 17:31 Comment(3)
I think OP's question was how to set a raw attribute, and this does not answer the question.Brockwell
If the code is handling a form save request, this would retrieve the old value that was loaded into the form instead of the new, current value.Pneumonoultramicroscopicsilicovolcanoconiosis
As @Brockwell points out, this ignores the property's accessor (only in Laravel < 8!!) not its mutator, which is not what OP asked for. It also doesn't get the current property's value, it gets the original value of the property (probably the DB's value), hence the name. In Laravel 8, getOriginal() is renamed to getOriginalRaw() and getOriginal() will use the accessor, as it should. Again, this isn't at all the right way to only get the raw value. TL;DR: this answer is wrong. It also misinforms readers. original != rawPlethora
E
20

If you need to skip Eloquent Model mutators once in a while (for example in unit tests) you should use setRawAttributes():

$model->setRawAttributes([
  'first_name' => 'Foobar',
]);
Embrue answered 29/4, 2019 at 11:30 Comment(2)
This will remove all the other attributes, to avoid that use as parameter array_merge(['first_name' => 'Foobar'], $model->toArray())Kus
@joão-hamerski when you have protected attributes, this will not work, rather try array_merge(getAttributes(), ['first_name' => 'Foobar']) This should be the accepted answer.Hogtie
R
6

What the OP is really want is the Raw value from database which does not goes through the given mutator and everyone is suggesting $model->getOriginal() but when you run this method the value still come through the mutator. So the real answer would the

$model->getRawOriginal('first_name')

This will give you the raw value skipping the mutator. Laravel API: getRawOriginal

Realtor answered 26/4, 2020 at 14:50 Comment(2)
Actually what OP really wants is to set a value in the DB, not get. They are after a mutator, not an accessor. This answer (and some others here) confuse this and don't answer the question.Euphroe
getRawOriginal worked for me. Thank youVitalis
O
2

I've got some problems when using setRawAttributes so I decided to use this approach

    public function setPasswordAttribute($value, $ignore = false)
    {
        if ($ignore)
            $this->attributes['password'] = $value;
        else
            $this->attributes['password'] = Hash::make($value);
    }

When you want to ignore mutator you can use $user->setPasswordAttribute('123', true)

Oversexed answered 13/5, 2021 at 7:53 Comment(0)
S
0

If you need to ignore mutators only on occasion - create another setter that doesn't go through the default mutation:

public function ignoreFirstNameMutator($value) {
    $this->attributes['first_name'] = $value;
}

$object->ignoreFirstNameMutator('Peter') //saves 'Peter'
Scribe answered 16/11, 2020 at 18:48 Comment(0)
M
0

it works for me :

$obj->getAttributes()['first_name']
Mimir answered 15/12, 2021 at 15:14 Comment(0)
B
0

You can use raw database statement

DB::statement('UPDATE users SET first_name = "' . $firstName . '" WHERE id = ' . $id);
Branchia answered 22/8 at 7:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.