Search code examples
phplaravellaravel-8laravel-socialitelaravel-jetstream

Laravel 8 Jetstream Profile Photos with Socialite Avatars


I'm trying Laravel 8 Jetstream with Laravel Socialite. The problem is when I retrieve the avatar and use its URL to profile_photo_path. The blade file appends http://localhost:8000/storage/ that is causing the avatar not to display. screenshot here

I have enabled jetstream's profile photos on config/jetstream.php

'features' => [
    Features::profilePhotos(),
    Features::accountDeletion(),
],

Here's how I store the user app/Http/Controllers/LoginController.php

    protected function registerOrLoginUser($user, $driver=null)
    {
        if(!is_null($driver)){
            $whereColumn = null;
            if($driver == 'facebook'){
                $whereColumn = "facebook_id";
            }
            if($driver == 'google'){
                $whereColumn = "google_id";
            }

            try{
                $findUser = User::where($whereColumn, $user->id)->first();
                if($findUser){
                    Auth::login($findUser);
                } else{
                    $newUser = new User();
                    $newUser->name = $user->name;
                    $newUser->email = $user->email;
                    $newUser->password = encrypt('');
                    $newUser->$whereColumn = $user->id;
                    $newUser->profile_photo_path = $user->getAvatar();
                    $newUser->save();
                    Auth::login($newUser);
                }

I saw the problem here resources/views/navigation-menu.blade.php

<button class="flex text-sm border-2 border-transparent rounded-full focus:outline-none focus:border-gray-300 transition duration-150 ease-in-out">
   <img class="h-8 w-8 rounded-full object-cover" src="{{ Auth::user()->profile_photo_url }}" alt="{{ Auth::user()->name }}" />
</button>

So I tried to remedy this blade file and put an if statement here :

<button class="flex text-sm border-2 border-transparent rounded-full focus:outline-none focus:border-gray-300 transition duration-150 ease-in-out">
    <img class="h-8 w-8 rounded-full object-cover" src="{{ (Auth::user()->google_id !== null ||  Auth::user()->facebook_id !== null ) ? Auth::user()->profile_photo_path : Auth::user()->profile_photo_url }}" alt="{{ Auth::user()->name }}" />
</button>

The 'If statement' is flawed, it would break when socialite logged-in users decided to change their picture. I tried this solution but it only stores numeric value to my profile_photo_path. Any idea how to make socialite and Jetstream's built-in profile photos work?


Solution

  • I copied getProfilePhotoUrlAtrribute method from vendor/laravel/jetstream/src/HasProfilePhoto.php to App\Models\User and modified it to accept avatar url from social site or retrieve uploaded photo.

    <?php
        public function getProfilePhotoUrlAttribute()
        {
    
            $path = $this->profile_photo_path;
    
            if (Storage::disk($this->profilePhotoDisk())->exists($path)){
                return Storage::disk($this->profilePhotoDisk())->url($this->profile_photo_path);
            } 
            elseif (!empty($path)){
                // Use Photo URL from Social sites link... 
                return $path;
            }
            else {
                //empty path. Use defaultProfilePhotoUrl
                return $this->defaultProfilePhotoUrl();
            }
        }
    ?>
    

    Jetsream docs reference