daugaard47's avatar

Custom Laravel Nova Avatars

I'm currently trying to get Nova to play nice with my existing website and existing users table.

My issue is with the Gravatar. I already have an avatar field in my users table and would like to display those rather the auto generated Gravatars.

In my Nova/User class I have the following. (Also changed to first_name and last_name)

    public function fields(Request $request)
    {
        return [
            ID::make()->sortable(),

           Gravatar::make('Avatar'),

            Text::make('First Name')
                ->sortable()
                ->rules('required', 'max:255'),

            Text::make('Last Name')
                ->sortable()
                ->rules('required', 'max:255'),

            Text::make('Email')
                ->sortable()
                ->rules('required', 'email', 'max:254')
                ->creationRules('unique:users,email')
                ->updateRules('unique:users,email,{{resourceId}}'),

            Password::make('Password')
                ->onlyOnForms()
                ->creationRules('required', 'string', 'min:8')
                ->updateRules('nullable', 'string', 'min:8'),
        ];
    }

When a user registers normally via the registration form, I'm doing the following with the avatar column from my auth > register controller. (I want to do the same in the Nova User Create)

RegisterController.php

    protected function create(array $data)
    {
        $hash = md5(strtolower(trim($data['email'])));
        $gravatar = 'http://www.gravatar.com/avatar/'.$hash.'??s=200&d=identicon';
        $user = User::create([
            'first_name' => $data['first_name'],
            'last_name' => $data['last_name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password']),
            'avatar' => $gravatar, // user DB `avatar` is set to a default image (default-avatar.png)
            'role_id' => '0', // DB is set to default 0
        ]);
}
  1. When I create a new user Via Nova, where/what is the form request that it is hitting?
  2. Where can I change the Nova/User view to display my avatars from my users database?
0 likes
3 replies
skauk's avatar

@daugaard47 When you create a User be it with Nova or any other way there are a number of events you can listen to and populate your avatar field accordingly. You can use event listeners or observers but for simple stuff, you can use this simple pattern: In your model class override the boot method:

protected static function boot()
{
    static::creating(function ($model) {
        $hash = md5(strtolower(trim($model->email)));
        $gravatar = 'http://www.gravatar.com/avatar/'.$hash.'??s=200&d=identicon';
        $model->avatar = $gravatar;
    });

    parent::boot();
}
daugaard47's avatar

@skauk This seems to be working great for generating the gravatar links via Nova. Thank you.

My other issue though is I currently have 300+ existing users. 1/3 has uploaded their own Avatar image and I would like to display those as well. How would I do this with Nova?

Example: (This is how I'm displaying the 3 optional avatars on the front-end.)

<div class="avatar-wrap">
    @php
    $userId = Auth::user()->id;
    $userAvatar = Auth::user()->avatar;
    @endphp
    // Option 1.
    // If User has 'DefaultAvatar.png' in the avatar column use this.
    @if (Auth::check() && (Auth::user()->avatar == 'DefaultAvatar.png'))
    <div class="..." style="background-image:url(/images/DefaultAvatar.png)"></div>

    // Option 2.
    // If User has 'Garavatar Link' in the avatar column use this.
    @elseif (strpos($userAvatar, 'gravatar') == true)
        <div class="..." style="background-image:url({{ $userAvatar }}"></div>

    @else
    // Option 3.
    // If User has 'Their Own Image' in the avatar column use this.
        <div class="..." style="background-image:url({{ asset("storage/images/users/$userId/avatar/$userAvatar") }}"></div>
    @endif
</div>

So how could I do this same logic in the Nova Users View?

How could I do something like this logic?

    $userId = User::user()->id;
    $userAvatar = User::user()->avatar;
 
    if ($user->avatar == 'DefaultAvatar.png'){
    // Option 1.
    // If User has 'DefaultAvatar.png' in the avatar column use this.
    return 'https://mysite.com/images/DefaultAvatar.png';

    }elseif (strpos($userAvatar, 'gravatar') == true){
    // Option 2.
    // If User has 'Garavatar Link' in the avatar column use this.
       return  $userAvatar;

   }else{
    // Option 3.
    // If User has 'Their Own Image' in the avatar column use this.
    return 'https://mysite.com/images/users/'.$userId.'/'.$userAvatar;
    }

If there a way to add this logic as a file system and then call it like this:

Avatar::make('Avatar')->disk('currentAvatars'),

This way was mentioned here: https://github.com/laravel/nova-issues/issues/2324#event-3008740340

skauk's avatar
skauk
Best Answer
Level 8

@daugaard47 You could put that logic into an accessor on the model and get it from everywhere, including Nova. In the model class:

public function getAvatarAttribute($value)
{
    if ($value == 'DefaultAvatar.png'){
        return 'https://mysite.com/images/DefaultAvatar.png';
    } elseif (strpos($value, 'gravatar') == true) {
        return  $value;
    }

    return "https://mysite.com/images/users/${this->id}/${value}";
}

Because you already have the avatar field on the model your $value parameter, in this case, will be the value of this field from the database.

1 like

Please or to participate in this conversation.