memento000
memento000

Reputation: 3

Display a default profile picture in Laravel

Users in my Laravel application have a profile_image column in their model/inside the database. It can be set to whichever image they like if they are a registered user but I've run into the problem that no image is set for their profile image, so it throws an error if you try to register a new user.

SQLSTATE[HY000]: General error: 1364 Field 'profile_image' doesn't have a default value (SQL: insert into users (name, email, password, updated_at, created_at) values

I tried using this, to check if the field is null so it returns the path for a default image to use. Else, it should return the user's profile_image value.

public function profileImage()
{
    if (is_null($this->profile_image)){
        $imagePath = 'defaultavatar.png';
    } else {
        $imagePath = $this->profile_image;
    }

    return '/storage/avatars/' . $imagePath;
}

And of course this gets used in the blade file on the user's profile.

<img src="{{ Auth::user()->profileImage() }}" class="img-fluid rounded-circle shadow-sm" height="150px" width="150px">

Doesn't seem to work though. It just gives the above sqlstate error.

Upvotes: 0

Views: 1853

Answers (2)

usrNotFound
usrNotFound

Reputation: 2830

You might be able to use Null Object Pattern

https://laravel.com/docs/8.x/eloquent-relationships#default-models

so, you would do something like this

public function profile() {
 return $this->belongsTo(Profile::class)
    ->withDefault([
         'image_path' => 'path to default image'
    ]);
}

So this way you are safe and always returning profile object.

Upvotes: 1

Donkarnash
Donkarnash

Reputation: 12845

You can make the profile_image column in database nullable to get rid of the error or you can fill a default value for profile_image column. There are two options to fill with default value for the profile image.

Option 1: (Handle at database level)

Set the default value for the profile_image column in the migration file to /storage/avatars/defaultavatar.png



use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->string('password');
            $table->timestamp('email_verified_at')->nullable();
            $table->string('profile_image')->default('/storage/avatars/defaultavatar.png')
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
}

Option2: (Handle in Controller)

When POST request with data to register a new user is received in the Controller, check whether profile_image has a value, if not fill in with the default

    protected funtion profileImagePath()
    {
        $path = '/storage/avatars/defaultavatar.png';
        if(request()->hasFile('profile_image') && request()->file('profile_image')->isValid()) {
            $path = request()->profile_image->store('avatars');
        }
        
        return $path;
    }

//$data is validated Request data received via registration form

/**
     * Create a new user instance after a valid registration.
     *
     * @param  array  $data
     * @return \App\User
     */
    protected function create(array $data)
    {
        return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password']),
            'profile_image' => $this->profileImagePath(),
        ]);
    }

Upvotes: 2

Related Questions