user2645113
user2645113

Reputation: 83

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?

Upvotes: 4

Views: 1943

Answers (2)

Todd Horst
Todd Horst

Reputation: 863

@user2645113's answer adapted for 2023, laravel 10. The source and destination files are the same, but now the function name is profilePhotoUrl.

Im sure this code could be refactored better, but here is a working version:

/**
     * Get the URL to the user's profile photo.
     *
     * @return \Illuminate\Database\Eloquent\Casts\Attribute
     */
    public function profilePhotoUrl(): Attribute
    {
        return Attribute::get(function () {

            $path = $this->profile_photo_path;

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

Obviously, be sure to include:

use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Support\Facades\Storage;

Upvotes: 0

user2645113
user2645113

Reputation: 83

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

Upvotes: 4

Related Questions