Search code examples
phplaravellaravel-validation

Laravel: How to use multiple validation rules with requests


I have two models User and Profile everything is working fine and creating a record perfectly.

For validation, I have created request classes as below.

UserRequest

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Validator;
use function __;
use function preg_match;

class UserRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     * @todo set role based permission for the method
     *
     */
    public function authorize()
    {
        return TRUE;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        Validator::extend(
            'without_spaces',
            function ($attr, $value) {
                return preg_match('/^\S*$/u', $value);
            },
            __('validation.username_space')
        );

        switch ($this->method()) {

            case 'POST':

                return [
                    'username' => 'required|string|without_spaces|max:255|unique:users',
                    'email'    => 'required|string|email|max:255|unique:users,email',
                    'password' => 'required|string|min:8|confirmed',
                    'role'     => 'required',
                ];

            case 'PUT':
            case 'PATCH':

                return [
                    'username' => 'sometimes|required|string|without_spaces|max:255|unique:users,username,' . $this->user->id,
                    'email'    => 'required|string|email|max:255|unique:users,email,' . $this->user->id,
                    'password' => 'nullable|string|min:8|confirmed',
                    'role'     => 'required',
                ];

            case 'GET':
            case 'DELETE':
            default:
                return [];
                break;
        }

    }
}

ProfileRequest

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use function __;
use function preg_match;

class ProfileRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return FALSE;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        Validator::extend('unique_field', function ($attributes, $value, $parameters, $validator) {
            return;
        },
            __('validation.username_space')
        );

        switch ($this->method()) {

            case 'POST':
            case 'PUT':
            case 'PATCH':

                return [
                    'first_name' => 'max:20',
                    'last_name'  => 'max:20',
                    'mobile'     => 'regex:/(01)[0-9]{9}/|digits:8 ',
                    'city'       => 'max:30',
                    'facebook'   => 'url',
                    'twitter'    => 'url',
                    'youtube'    => 'url',
                    'instagram'  => 'url',
                ];

            case 'GET':
            case 'DELETE':
            default:
                return [];
                break;
        }
    }
}

UserController

public function store(UserRequest $request)
{
    // begin transaction
    DB::beginTransaction();

    try {
        // create user
        $user = User::create([
            'username' => $request->username,
            'email'    => $request->email,
            'password' => Hash::make($request->password),
            'role'     => $request->role,
        ]);

        // set profile data
        $profile = new Profile([
            'first_name' => $request->first_name,
            'last_name'  => $request->last_name,
            'mobile'     => $request->mobile,
            'city'       => $request->city,
            'facebook'   => $request->facebook,
            'twitter'    => $request->twitter,
            'youtube'    => $request->youtube,
            'instagram'  => $request->instagram,
        ]);

        // save profile data
        $user->profile()->save($profile);

        // commit transaction
        DB::commit();

        // if user created
        if ($user) {
            return redirect(route('admin.users.index'))->with('success', __('messages.admin.feedback.user_created'));
        } else {
            return redirect(route('admin.users.index'))->with('error', __('messages.admin.feedback.user_created'));
        }

    } catch (Throwable $exception) {
        // rollback if error
        DB::rollBack();

        throw $exception;
    }

}

public function update(UserRequest $request, User $user)
{

    try {

        $user->email = $request->email;
        $user->role  = $request->role;

        if ($request->has('password')) {
            $user->password = Hash::make($request->password);
        }

        $user->save();

        // set profile data
        $profile = [
            'first_name' => $request->first_name,
            'last_name'  => $request->last_name,
            'mobile'     => $request->mobile,
            'city'       => $request->city,
            'facebook'   => $request->facebook,
            'twitter'    => $request->twitter,
            'youtube'    => $request->youtube,
            'instagram'  => $request->instagram,
        ];

        // save profile data
        $user->profile()->update($profile);

        return redirect(route('admin.users.index'))->with('success', __('messages.admin.feedback.user_updated'));

    } catch (Throwable $exception) {
        throw $exception;
    }
}

Question:

I have one single form for user fields and profile fields. Now I am not sure how to use both request classes in method to validate fields.


Solution

  • I have found a workaround. Type-hit the ProfileRequest class in store and update methods and used it to validate profile fields.

    UserController

    public function store(UserRequest $request, ProfileRequest $profileRequest)
    {
        // begin transaction
        DB::beginTransaction();
    
        try {
            // create user
            $user = User::create([
                'username' => $request->username,
                'email'    => $request->email,
                'password' => Hash::make($request->password),
                'role'     => $request->role,
            ]);
    
            // set profile data
            $profile = new Profile([
                'first_name' => $profileRequest->first_name,
                'last_name'  => $profileRequest->last_name,
                'mobile'     => $profileRequest->mobile,
                'city'       => $profileRequest->city,
                'facebook'   => $profileRequest->facebook,
                'twitter'    => $profileRequest->twitter,
                'youtube'    => $profileRequest->youtube,
                'instagram'  => $profileRequest->instagram,
            ]);
    
            // save profile data
            $user->profile()->save($profile);
    
            // commit transaction
            DB::commit();
    
            // if user created
            if ($user) {
                return redirect(route('admin.users.index'))->with('success', __('messages.admin.feedback.user_created'));
            } else {
                return redirect(route('admin.users.index'))->with('error', __('messages.admin.feedback.user_created'));
            }
    
        } catch (Throwable $exception) {
            // rollback if error
            DB::rollBack();
    
            throw $exception;
        }
    
    }
    
    public function update(UserRequest $request, ProfileRequest $profileRequest, User $user)
    {
    
        try {
    
            $user->email = $request->email;
            $user->role  = $request->role;
    
            if ($request->has('password')) {
                $user->password = Hash::make($request->password);
            }
    
            $user->save();
    
            // set profile data
            $profile = [
                'first_name' => $profileRequest->first_name,
                'last_name'  => $profileRequest->last_name,
                'mobile'     => $profileRequest->mobile,
                'city'       => $profileRequest->city,
                'facebook'   => $profileRequest->facebook,
                'twitter'    => $profileRequest->twitter,
                'youtube'    => $profileRequest->youtube,
                'instagram'  => $profileRequest->instagram,
            ];
    
            // save profile data
            $user->profile()->update($profile);
    
            return redirect(route('admin.users.index'))->with('success', __('messages.admin.feedback.user_updated'));
    
        } catch (Throwable $exception) {
            throw $exception;
        }
    }