Hichxm
Hichxm

Reputation: 33

Laravel: Why Laravel accessor not work getIsVerifiedAttribute()?

I need to check the email of my users. So I add a new attribute to my User model named "is_verified" that returns me a boolean to know if the user has checked the email or not.

I running on PHP 7.2.5 with PHPUnit 7.5.15 and Laravel 5.8

model: User.php

<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Support\Str;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'email', 'password', 'token', 'email_verified_at'
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    /**
     * Retrive if user as vierfied
     *
     * @return boolean
     */
    public function getIsVerifiedAttribute()
    {
        // dump(!is_null($this->email_verfied_at));

        return !is_null($this->email_verfied_at);
    }

    /**
     * Set if user is verified
     *
     * @param boolean $status
     * @return void
     */
    public function setIsVerifiedAttribute(bool $value)
    {
        if ($value) {
            $this->attributes['token'] = null;
            $this->attributes['email_verified_at'] = now();
        } else {
            $this->attributes['token'] = self::generateToken();
            $this->attributes['email_verified_at'] = null;
        }
    }


    /**
     * Generate token to verify email
     *
     * @param integer $length
     * @return string
     */
    public static function generateToken(int $length = 64): string
    {
        $token = Str::random($length);

        if (self::where('token', $token)->exists())
        {
            return self::generateToken($length);
        }

        return $token;
    }

}

My unit test:

    /** @test */
    public function check_if_user_as_validate_email()
    {
        $user = factory(User::class)->create();

        $this->assertFalse($user->is_verified);

        $user->is_verified = true;
        $user->save();

        $this->assertTrue($user->is_verified);

        $user->is_verified = false;
        $user->save();

        $this->assertFalse($user->is_verified);
    }

The functions do not return me the good value every time

Upvotes: 0

Views: 412

Answers (1)

Rwd
Rwd

Reputation: 35190

The reason your test isn't working is because you have a typo in your getIsVerifiedAttribute accessor. email_verfied_at should be email_verified_at.

public function getIsVerifiedAttribute()
{
    return !is_null($this->email_verified_at);
}

Out-of-the-box, the User factory sets the email_verified_at field for you so I would suggest you change the code in your test for creating a User to:

$user = factory(User::class)->create([
    'email_verified_at' => null
]);

This next bit is just an FYI but there are already methods included in with Laravel to check if a User is verified or not and to set the email_verified_at value:

$user->hasVerifiedEmail();

and

$user->markEmailAsVerified();

Upvotes: 3

Related Questions