Link to home
Create AccountLog in
Avatar of Marco Gasi
Marco GasiFlag for Spain

asked on

Laravel form validation error

Hi everybody.
I'm learning Laravel and I've got an issue with the Auth code. The issue is that Laravel seems to pretend that to register a new user all registration form fields be filled, even the not required ones.

This is my RegisterController.php
<?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;
use Illuminate\Http\Request;
use Illuminate\Auth\Events\Registered;

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'],
      'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
      'password' => ['required', 'string', 'min:8', 'confirmed'],
      'company' => ['string'],
      'website' => ['string'],
      'phone' => ['numeric'],
      'mobile' => ['numeric'],
      'type' => ['string'],
    ]);
  }

  /**
   * 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']),
     //using data_get doesn't change anything
      'company' => data_get( $data, 'company'),
      'website' => data_get($data, 'website'),
      'phone' => data_get($data, 'phone'),
      'mobile' => data_get($data, 'mobile'),
    	'type' => data_get($data, 'type'),
      // 'company' => $data['company'],
      // 'website' => $data['website'],
      // 'phone' => $data['phone'],
      // 'mobile' => $data['mobile'],
    	// 'type' => $data['type'],
    ]);
  }

  /**
   * https://laraveldaily.com/auth-after-registration-redirect-to-previous-intended-page/
   * Handle a registration request for the application.
   *
   * @param  \Illuminate\Http\Request  $request
   * @return \Illuminate\Http\Response
   */
  public function register(Request $request)
  {
    $this->validator($request->all())->validate();

    event(new Registered($user = $this->create($request->all())));

    $this->guard()->login($user);

    return $this->registered($request, $user)
      ?: redirect()->intended($this->redirectPath());
  }

}

Open in new window


I originally followed a tutorial. Later I wanted to add some field to user table and I used this migration:
<?php

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

class AddPersonalDataToUserTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->string('company')->nullable();
            $table->string('website')->nullable();            
            $table->string('phone')->nullable();            
            $table->string('mobile')->nullable();            
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn(['company',  'website', 'phone', 'mobile']);
        });
    }
}

Open in new window


I thought that leaving added columns empty whould have worked fine but I've got validation errors like "The website must be a string", so I googled a bit and I have created a new migration:
<?php

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

class AddDefaultNullToSomeColumn extends Migration
{
	/**
	 * Run the migrations.
	 *
	 * @return void
	 */
	public function up()
	{
		Schema::table('users', function (Blueprint $table) {
			$table->string('company')->nullable()->default(null)->change();
			$table->string('website')->nullable()->default(null)->change();
			$table->string('phone')->nullable()->default(null)->change();
			$table->string('mobile')->nullable()->default(null)->change();
		});
	}

	/**
	 * Reverse the migrations.
	 *
	 * @return void
	 */
	public function down()
	{
		Schema::table('users', function (Blueprint $table) {
			$table->string('company')->nullable()->change();
			$table->string('website')->nullable()->change();
			$table->string('phone')->nullable()->change();
			$table->string('mobile')->nullable()->change();
		});
	}
}

Open in new window


and finally, here there is my registration form
@extends('master')
@section('title', __('auth.registerTitle') )

@section('content')
<div class="hero-wrap hero-wrap-2" style="background-image: url('/images/bg_2b.jpg');" data-stellar-background-ratio="0.5">
  <div class="overlay"></div>
  <div class="container">
    <div class="row no-gutters slider-text align-items-center justify-content-center">
      <div class="col-md-8 ftco-animate text-center text-center mt-5">
        <p class="breadcrumbs mb-0"><span class="mr-3"><a href="/">{{ __('menu.home') }} <i class="ion-ios-arrow-forward"></i></a></span> <span>{{ __('auth.menu-register') }}</span></p>
        <h1 class="mb-3 bread">{{ __('auth.menu-register') }}</h1>
      </div>
    </div>
  </div>
</div>

<section class="ftco-section ftco-partner">
  <div class="container">
    <div class="row block-9 justify-content-center mb-5">
      <div class="col-md-10 mb-md-5">

        <h2 class="float-left">{{ __('auth.registerTitle') }}</h2>
        <form method="post">
          @foreach ($errors->all() as $error)
            <p class="alert alert-danger">{{ $error }}</p>
          @endforeach

          {{ csrf_field() }}
          <div class="form-group">
          <label for="name" class="col-lg-12 control-label">{{ __('auth.name') }}</label>
            <div class="col-lg-12">
              <input type="text" class="form-control" id="name" placeholder="{{ __('auth.name') }}" name="name" value="{{ old('name') }}">
            </div>
          </div>

          <div class="form-group">
            <label for="email" class="col-lg-12 control-label">{{ __('auth.email') }}</label>
            <div class="col-lg-12">
              <input type="email" class="form-control" id="email" placeholder="{{ __('auth.email') }}" name="email" value="{{ old('email') }}">
            </div>
          </div>

          <div class="form-group">
            <label for="password" class="col-lg-12 control-label">{{ __('auth.pwd') }}</label>
            <div class="col-lg-12">
              <input type="password" class="form-control"  name="password">
            </div>
          </div>

          <div class="form-group">
            <label for="password" class="col-lg-12 control-label">{{ __('auth.pwdrepeat') }}</label>
            <div class="col-lg-12">
              <input type="password" class="form-control"  name="password_confirmation">
            </div>
          </div>

          <div class="form-group">
            <label for="company" class="col-lg-12 control-label">{{ __('auth.company') }}</label>
            <div class="col-lg-12">
              <input type="text" class="form-control" id="company" placeholder="{{ __('auth.company') }}" name="company" value="{{ old('company') }}">
            </div>
          </div>

          <div class="form-group">
            <label for="website" class="col-lg-12 control-label">{{ __('auth.website') }}</label>
            <div class="col-lg-12">
              <input type="text" class="form-control" id="website" placeholder="{{ __('auth.website') }}" name="website" value="{{ old('website') }}">
            </div>
          </div>

          <div class="form-group">
            <label for="phone" class="col-lg-12 control-label">{{ __('auth.phone') }}</label>
            <div class="col-lg-12">
              <input type="text" class="form-control" id="website" placeholder="{{ __('auth.phone') }}" name="phone" value="{{ old('phone') }}">
            </div>
          </div>

          <div class="form-group">
            <label for="mobile" class="col-lg-12 control-label">{{ __('auth.mobile') }}</label>
            <div class="col-lg-12">
              <input type="text" class="form-control" id="mobile" placeholder="{{ __('auth.mobile') }}" name="mobile" value="{{ old('mobile') }}">
            </div>
          </div>

          {{-- <div class="form-group">
            <label for="type" class="col-lg-12 control-label">{{ __('auth.type') }}</label>
            <div class="col-lg-12">
                <select class="form-control" name="type" id="type">
                    <option value="admin">Admin</option>
                    <option value="super_admin">Super Admin</option>
                    <option value="member">Member</option></select>
            </div>
          </div> --}}

          <div class="form-group">
            <div class="col-lg-10 col-lg-offset-2">
							<input type="hidden" name="type" id="type" value="member" />
              <button type="reset" class="btn btn-default">{{ __('auth.cancel') }}</button>
              <button type="submit" class="btn btn-primary">{{ __('auth.submit') }}</button>
            </div>
          </div>
        </form>
      </div>
    </div>
  </div>
</section>
@endsection

Open in new window

Actually, the db table allows those fields to be NULL and their default value is NULL but I still get those errors and to successfully register a new user I must fill all fields in the form.
What I am missing here?
ASKER CERTIFIED SOLUTION
Avatar of Chris Stanyon
Chris Stanyon
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
Create an account to see this answer
Signing up is free. No credit card required.
Create Account
Avatar of Marco Gasi

ASKER

Hi Chris, thank you for your answer.
I'm using Laravel 6.0.
I thought that just declaring fields as nullable in the migration were enough :)
Going to try your suggestion.
Thank you, Chris, it works like a charm.
No worries Marco,

Glad I could help.

FYI -  the Validations in your controller, aren't directly related to the tables (although it will help to prevent invalid data being saved to your DB)
the Validations in your controller, aren't directly related to the tables (although it will help to prevent invalid data being saved to your DB)
I'm not sure to understand what you mean.... Actually, no, I'm absolutely sure I don't :)
Hey Marco,

In your comments you said that the DB columns allow null but you still get the error.

My point was that you're dealing with 2 separate issues here - when you post a form to a controller, you validate the data against a set of rules. Your data either passes or fails the validation. This has nothing to do with your Database, the Tables or the Columns - you're simply validating the data a user has submitted.

After the data has been validated, you then store that data into the database - as a separate process.

That's why I said that the Validations aren't related to your Tables.
Okay, thank you so much for the additional input, very clear. Ciao.