phplaraveluser-registration

Extract email field from 'User' model and add it to a seperate model 'Email' via foreign key


I'm pretty new to Laravel and was instructed to seperate the field 'email' from the 'User' model and instead use an foreign_id that corresponds with a newly created model 'Email'.

Users:

public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->id();
        $table->integer('email_id');
        $table->string('password');
        $table->rememberToken();
        $table->timestamps();
    });
}

Emails:

public function up()
{
    Schema::create('emails', function (Blueprint $table) {
        $table->id();
        $table->string('email')->unique();
        $table->timestamp('email_verified_at')->nullable();
        $table->boolean('is_active')->default(True);
        $table->timestamps();
    });
}

Of course I've already set the relations in those models.

Now when a new user registers via form I want to check whether the entered mail address already exists in the 'emails' table and whether the mail address that might have been found has the property 'is_active' set to true.

Currently the 'validator' and 'create' functions in the RegisterController are pretty basic:

/**
 * 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'],
    ]);
}

/**
 * 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']),
    ]);
}

Is there a way to accomplish this in a sensible way? And also are there other files that would have to be adapted in order for this to work properly?

Greetings, Frame


Solution

  • As you want to check that there should not exist an email in the database which is active, you need to use unique validation rule. https://laravel.com/docs/7.x/validation#rule-unique

    use Illuminate\Validation\Rule;
    

    Add this rule in your the rules.

    'email' => ['required', 'string', 'email', 'max:255', Rule::unique('emails', 
                 'email')->where(function($query) {
                  return $query->where('is_active', TRUE);
               })
    ],
    

    Controller

    protected function create(array $data)
    {
        $email = Email::create([
              'email' => $data['email']
        ]);
    
        return User::create([
            'email_id' => $email->id,
            'password' => Hash::make($data['password']),
        ]);
    }