4
votes

I'm currently trying to modify the laravel Auth two be able to register two different kinds of users, a seller and a buyer. Both have the same form, except one field, that only the seller has, called companyName.

So what I did is putting a dropdown for registration instead of the normal register button, this is what I got there:

<div class="dropdown">
                            <button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
                                Registrieren
                                <span class="caret"></span>
                            </button>
                            <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
                            <li>
                                <a href="{{url('/register/customer')}}">Als Käufer</a>
                                <a href="{{url('/register/seller')}}">Als Händler</a>
                            </li>
                            </ul>
                        </div>

Then I made a route for this two kinds of registrations, like this:

Route::get('/register/{userType}', 'Auth\RegisterController@showRegistrationForm');

In the controller then I simply overwrote this showRegistrationForm function to pass the userType into my view, just like that:

 public function showRegistrationForm($userType)
    {
        return view('auth.register', ['userType'=> $userType]);
    }

And in my view, I got this:

@extends('master')

@section('content')
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <div class="panel panel-default">
                    <div class="panel-heading">Registrieren
                        als <?php if ($userType == 'customer') echo "Käufer";if ($userType == 'seller') echo "Verkäufer";?></div>
                    <div class="panel-body">
                        <form class="form-horizontal" role="form" method="POST" action="{{ url('/register') }}">
                            {{ csrf_field() }}

                            <div class="form-group{{ $errors->has('sex') ? ' has-error' : '' }}">
                                <label for="sex" class="col-md-4 control-label">Anrede</label>
                                <div class="col-md-6">

                                    <select class="form-control" id="sex">
                                        <option value="male">Herr</option>
                                        <option value="female">Frau</option>
                                </select>
                                </div>

                                @if ($errors->has('sex'))
                                    <span class="help-block">
                                        <strong>{{ $errors->first('sex') }}</strong>
                                    </span>
                                @endif
                            </div>

                            <div class="form-group{{ $errors->has('name') ? ' has-error' : '' }}">
                                <label for="firstName" class="col-md-4 control-label">Vorname</label>

                                <div class="col-md-6">
                                    <input id="firstName" type="text" class="form-control" name="firstName"
                                           value="{{ old('firstName') }}" required autofocus>

                                    @if ($errors->has('firstName'))
                                        <span class="help-block">
                                        <strong>{{ $errors->first('firstName') }}</strong>
                                    </span>
                                    @endif
                                </div>
                            </div>

                            <div class="form-group{{ $errors->has('name') ? ' has-error' : '' }}">
                                <label for="name" class="col-md-4 control-label">Nachname</label>

                                <div class="col-md-6">
                                    <input id="name" type="text" class="form-control" name="name"
                                           value="{{ old('name') }}" required autofocus>

                                    @if ($errors->has('name'))
                                        <span class="help-block">
                                        <strong>{{ $errors->first('name') }}</strong>
                                    </span>
                                    @endif
                                </div>
                            </div>

                            <?php if ($userType == 'seller'){ ?>
                            <div class="form-group{{ $errors->has('companyName') ? ' has-error' : '' }}">
                                <label for="companyName" class="col-md-4 control-label">Firmenname</label>

                                <div class="col-md-6">
                                    <input id="companyName" type="text" class="form-control" name="companyName"
                                           value="{{ old('companyName') }}" required autofocus>

                                    @if ($errors->has('companyName'))
                                        <span class="help-block">
                                        <strong>{{ $errors->first('companyName') }}</strong>
                                    </span>
                                    @endif
                                </div>
                            </div>
                            <?php } ?>

                            <div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">
                                <label for="email" class="col-md-4 control-label">E-Mail Addresse</label>

                                <div class="col-md-6">
                                    <input id="email" type="email" class="form-control" name="email"
                                           value="{{ old('email') }}" required>

                                    @if ($errors->has('email'))
                                        <span class="help-block">
                                        <strong>{{ $errors->first('email') }}</strong>
                                    </span>
                                    @endif
                                </div>
                            </div>

                            <div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">
                                <label for="password" class="col-md-4 control-label">Passwort</label>

                                <div class="col-md-6">
                                    <input id="password" type="password" class="form-control" name="password" required>

                                    @if ($errors->has('password'))
                                        <span class="help-block">
                                        <strong>{{ $errors->first('password') }}</strong>
                                    </span>
                                    @endif
                                </div>
                            </div>

                            <div class="form-group{{ $errors->has('password_confirmation') ? ' has-error' : '' }}">
                                <label for="password-confirm" class="col-md-4 control-label">Passwort
                                    wiederholen</label>

                                <div class="col-md-6">
                                    <input id="password-confirm" type="password" class="form-control"
                                           name="password_confirmation" required>

                                    @if ($errors->has('password_confirmation'))
                                        <span class="help-block">
                                        <strong>{{ $errors->first('password_confirmation') }}</strong>
                                    </span>
                                    @endif
                                </div>
                            </div>

                            <div style="display:none;" class="form-group{{ $errors->has('role') ? ' has-error' : '' }}">
                                <label for="role" class="col-md-4 control-label">Deine Rolle:</label>

                                <div class="col-md-6">
                                    <input name="role" type="radio"
                                           <?php if ($userType == 'customer') echo "checked";?> value="Käufer">&nbsp;Käufer<br/>
                                    <input name="role" type="radio"
                                           <?php if ($userType == 'seller') echo "checked";?> value="Verkäufer">&nbsp;Verkäufer

                                    @if ($errors->has('role'))
                                        <span class="help-block">
                                        <strong>{{ $errors->first('role') }}</strong>
                                    </span>
                                    @endif
                                </div>
                            </div>

                            <div class="form-group">
                                <div class="col-md-6 col-md-offset-4">
                                    <button type="submit" class="btn btn-primary">
                                        Registrieren
                                    </button>
                                </div>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </div>
@endsection

So mostly basic, just few more fields then with the auth without modification and the companyName only showing up when accessed over the route /register/seller.

My RegisterController is of course also a bit modified, or especially the create function, it looks like this now:

 protected function create(array $data)
    {
        $user = User::create([
            'name' => $data['name'],
            'firstName' => $data['firstName'],
            'sex' => $data['sex'],
            'email' => $data['email'],
            'username' => $data['username'],
            'password' => bcrypt($data['password']),
            'role' => $data['role'],
            'templateURL' => ""
        ]);     

        if($data['role'] == 'Verkäufer'){
            Complaint::create([
               'user_id' => $user->id,
               'complaintCount' => 0
            ]);
        }

        switch($data['role']){
            case 'Käufer':
                $user->attachRole(2);
                break;
            case 'Verkäufer':
                $user->attachRole(3);
                $user->companyName = $data['companyName'];
                $user->save();
                break;
            default:
                $user->attachRole(2);
                break;
        }


        return $user;
    }

And now comes the problem: As you can see, in my "invidual" views, which is basically just one anyway, I still post to the url /register, which I thought should work, but it doesn't.... Any ideas why this is not working? I also tried to add individual routes, so something like that:

Route::post('/register/seller', 'Auth\RegisterController@create');
Route::post('/register/buyer', 'Auth\RegisterController@create');

but thats not working as well. In both cases, I just get the same window back, as if there was an error (so my data still entered (expect the password), but nothing is registered or entered in the db, but as well there are no errors showing up, neither in my view, nor in the console.

What's interesting as well is the network tab, it seems like it definetely sends the request to /register as it shows up there with status code 302, but as well there's the route /register/customer again, and I'm wondering why...What's also interesting is that I think that somehow it kinda works, as if I enter a password with less then 6 characters or 2 different passwords, I get an error, so somehow the form seems to be posted, but nothing is entered into the db....

Any ideas why this happens like this and whats the problem?

1
For such use cases.... I prefer building my own AuthController...prateekkathal
@prateekkathal You mean your own RegisterController? What would it change?...nameless
First of all you will have control of how you want the things to be saved in your database. Second, you will have control of what routes to follow and for what purposes. :)prateekkathal
Can you give me an example of how to implement such a controller and how to use mine then instead of the default onenameless
Can you tell me how your tables/relations are created?prateekkathal

1 Answers

2
votes

First of all, I'd like to suggest you a Polymorphic approach to saving the users. Right now, you have only 2 user types, what if you get a third user type (say retailer or wholesaler or blah blah)... and for each of them, you will require different fields which may or may not fit in for all user types...

So, go with this

class User
{
  public function profile()
  {
    return $this->morphTo();
  }
}

class Seller
{
  public function user()
  {
    return $this->morphOne('App\User', 'profile');
  }
}

class Buyer
{
  public function user()
  {
    return $this->morphOne('App\User', 'profile');
  }
}

Now, In your routes, add these

Route::get('login', 'LoginController@show')->name('login.show');
Route::post('login', 'LoginController@login')->name('login.post');

Route::get('register', 'RegisterController@show')->name('register.show');
Route::post('register', 'RegisterController@register')->name('register.post');

Route::get('logout', 'LoginController@logout')->name('login.logout');

Now, in your form add a dropdown/radio button for User Type selection (you can also make seprate and run different routes and make these fields hidden);

Say,

<select name="type">
  <option value="1">Buyer</option>
  <option value="2">Seller</option>
<select>

Your RegisterController@register can be as follows:

use App\Buyer;
use App\Seller;
use Validator;

class RegisterController extends Controller
{
  public function show()
  {
    return view('auth.register');
  }

  public function register()
  {
    $inputs = request()->all();

    $validator = $this->validator($inputs);

    if($validator->fails()) {
      return redirect()->back()->withErrors($validator)->withInput();
    }

    $userInputs = array_only($inputs, ['name', 'email', 'password']);
    $userInputs['password'] = Hash::make($userInputs['password']);

    switch($inputs['type'])
    {
      case 1:
        $sellerInputs = array_only($inputs, ['company_name']);

        $seller = Seller::create();
        $user = $seller->user()->create($userInputs);
      case 2: 
        $buyer = Buyer::create();
        $user = $buyer->user()->create($userInputs);
      default:
        $user = null;
        break;
    }

    if(!$user) {
      return redirect()->back(); //Show flash messsage etc... and redirect back to show an error
    }

    auth()->attempt(array_only($inputs, ['email', 'password']));
    return redirect(route('some.route'));
  }

  protected validator($inputs)
  {
    $rules = [
      'name' => 'required|min:1|max:50',
      'email' => 'required|email|min:1|max:100',
      'password' => 'required|min:6|max:25',
      // Other rules
    ];

    $messages = [
      // Any special messages if required...
    ];

    return Validator::make($inputs, $rules, $messages);
  }
}

Use same kind of coding structure in LoginController... I am simply going to write the login behind logging in below

public function login()
{
  $inputs = request()->all();

  //Validator etc...

  if(auth()->attempt(array_only($inputs, ['email', 'password']))) {
    return redirect(route('some.route'));
  } else {
    return redirect()->back(); // Again... Show some error flash message
  }
}

Note :- I have not tested the code but I am 99% sure this should work... I wrote all this down myself... Took a damn half an hour almost!

Hope everything is answered and you understood. Let me know in the comments below if you have any other query :)