php – How can I store avatar(image file) through Auth/RegisterController while user registration?-ThrowExceptions

Exception or error:

My intention is to store a profile pic with user registration. I am using Laravel 6 User Authentication. I tried to do it in given method.

My html code is like this..

<form method="POST" action="{{ route('register') }}" enctype="multipart/form-data">
    @csrf
    <input type="text" name="name" placeholder="Name"><br>
        @error('name')
            <div>{{$message}}</div>
        @enderror
    <input type="file" name="avatar" placeholder="Profile photo"><br>
        @error('avatar')
            <div>{{$message}}</div><br>
    @enderror
</form>

I added validation in Auth/RegisterController.validator().
I added fields to store data to create function.
RegisterController class is given below..

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use App\User;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;

class RegisterController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Register Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles the registration of new users as well as their
    | validation and creation. By default this controller uses a trait to
    | provide this functionality without requiring any additional code.
    |
    */

    use RegistersUsers;

    /**
     * Where to redirect users after registration.
     *
     * @var string
     */
    protected $redirectTo = RouteServiceProvider::HOME;

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest');
    }

    /**
     * Get a validator for an incoming registration request.
     *
     * @param  array  $data
     * @return \Illuminate\Contracts\Validation\Validator
     */
    protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => ['required', 'string', 'max:255'],
            'avatar' => ['mimes:jpeg,jpg,png,gif','required','max:10000']
        ]);
    }
    /**
     * 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'],
            'avatar' => file($data['avatar'])->store('avatars')
        ]);
    }
}

When I try to run this code, this error will occur

Error
Call to a member function store() on array
http://localhost:8000/register 

Note: I removed email, password and other fields just to reduce number of lines..

How to solve:

You can upload avatar with laravel default registration by doing following steps.

1) Add avatar field in your migration

$table->string('avatar');

2) Add avatar field in $filable in User model

protected $fillable = [
    'name', 'email', 'password', 'avatar',
];

3) Add avatar input field in register.blade.php

<div class="form-group row">
    <label for="avatar" class="col-md-4 col-form-label text-md-right">{{ __('Avatar') }}</label>

    <div class="col-md-6">
        <input id="avatar" type="file" class="form-control @error('avatar') is-invalid @enderror" name="avatar" value="{{ old('avatar') }}" required autocomplete="avatar" autofocus>

        @error('avatar')
            <span class="invalid-feedback" role="alert">
                <strong>{{ $message }}</strong>
            </span>
        @enderror
    </div>
</div>

4) Add avatar in the validator function for validation

protected function validator(array $data)
{
    return Validator::make($data, [
        'name' => ['required', 'string', 'max:255'],
        'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
        'password' => ['required', 'string', 'min:6', 'confirmed'],
        'avatar' => ['required', 'image'],
    ]);
}

5) Handle file upload in create function

protected function create(array $data)
{
    $request = app('request');
    if ($request->hasfile('avatar')) {
        $avatar = $request->file('avatar');
        $filename = time() . '.' . $avatar->getClientOriginalExtension();

        //Implement check here to create directory if not exist already 

        Image::make($avatar)->resize(300, 300)->save(public_path('uploads/avatars/' . $filename));
    }

    return User::create([
        'name' => $data['name'],
        'email' => $data['email'],
        'password' => Hash::make($data['password']),
        'avatar' => !empty($filename) ? $filename : 'default_avatar.png',
    ]);
}

6) Before you try to Run this make sure you have Image Class available in your controller, If you don’t have image class you can include it in your project by doing following steps.

composer require intervention/image

Now open the config/app.php file. Add this to the $providers array.

Intervention\Image\ImageServiceProvider::class

Next add this to the $aliases array.

'Image' => Intervention\Image\Facades\Image::class

Now include Image class in User Controller like this

use Image;

Try to run your project, it should work fine.

Leave a Reply

Your email address will not be published. Required fields are marked *