Как создать проверку вложенной модели для вызова в запросе в Laravel - PullRequest
1 голос
/ 20 января 2020

У меня есть структура таблицы базы данных, подобная следующей (в laravel):

  • профиль пользователя 1-1
  • профиль партнера 1-1
  • пользователь 1-N отдел

Я хочу отправить запрос на сохранение (публикацию), чтобы пользователь прошел валидацию в UserRequest и этот класс вызывал ProfileRequest.

  • Это можно сделать?
  • Есть ли способ выполнить валидацию связанных моделей?

Пример запроса класса пользователя:


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

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [

            'name' => 'required|string',
            'lastname' => 'required|string',
            'user' => [
                'required',
                Rule::unique('users')->ignore($this),
            ],
            'email' => 'required|string|email|unique:users',
            'password' => 'required|string|confirmed',
            'headquarter_id' => 'required'

            //Validation of profile

        ];
    }
}

Пример пользователя контроллера

    public function store(AdAszaUserRequest $request)
    {
        $input = $request->all();
        $validated = $request->validated();
        $input['password'] = \Hash::make($request['password']);
        //   

        $departmentidList = array_column($input['departments'], 'id');        

        $AszaUser = AdAszaUser::create($input);  

        $models = [];
        foreach ($input['departments'] as $model) {
            $models[] = new AdDepartment($model);
        }

///important: this line add departments without validation
        $AszaUser->departments()->saveMany($models);
        $AszaUser->departments()->sync($departmentidList);


        return response($AszaUser, 201);
    }

и запрос на отправку:

<?php

namespace App\Http\Requests\AD;

use Illuminate\Foundation\Http\FormRequest;

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

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'name' => 'required|string|unique:ad_departments',
            'internal_name' => 'required|string|unique:ad_departments'            
        ];
    }
}

Пример Json отправка сообщения:

{
    "id":2,
    "name": "Admin2",
    "email": "test@gmail.com",
    "lastname": "test",
    "user": "test",
    "password": "test",
    "password_confirmation": "test",
    "headquarter_id": 1,
    "lastname":"test",
    "remember_token": "1",
    "email_verified_at": "test",
    "headquarter": {
            "id": 1,
            "name": "ASZA ZARAGOZA",
            "description": "Sede en Zaragoza",
        },
         "departments": [
            {
                "id": 1,
                "name": "Intérpretes",
                "internal_name": "Interprete",
                "description": "Departamento de Intérpretes",
                "display_id": "01",
                "pivot": {
                    "user_id": 1,
                    "department_id": 1
                }
            },
            {
                "id": 10,
                "name": "Psicología"
            }
        ]
}

Могу ли я вызвать DepartmentRequest для проверки элементов, переданных в массиве отдела

Ответы [ 2 ]

1 голос
/ 21 января 2020

ОБНОВЛЕНИЕ: 1 Я не думаю, что это необходимо, но, конечно, это возможно

    public function store(AdAszaUserRequest $request)
    {
        $input = $request->all();
        $validated = $request->validated();
        $input['password'] = \Hash::make($request['password']);
        //   

        $departmentidList = array_column($input['departments'], 'id');        

        $AszaUser = AdAszaUser::create($input);  

        $models = [];
        foreach ($input['departments'] as $model) {
            /** To check validation for single item */
            $validator = Validator::make($model, (new StoreEventRequest)->rules());
            if (!$validator->fails()) {
                $models[] = new AdDepartment($model);
            } else {
                /** Something wrong */
                /** $errors = $validator->errors(); */
            }
        }

        /** To check validation for array of data
        $validator = Validator::make($request->only(['departments']), collect(array_map(function ($rules, $field): array {
            return ['departments.*.' . $field => $rules];
        }, (new StoreEventRequest)->rules()))
            ->collapse()
            ->toArray()); */

        /**
         * And then do what you want to do with this object
         * $errors = $validator->errors();
         *
        if ($validator->fails()) {
            return redirect('some_url')
                ->withErrors($validator);
        } */

        $AszaUser->departments()->saveMany($models);
        $AszaUser->departments()->sync($departmentidList);


        return response($AszaUser, 201);
    }

Для получения дополнительной информации см. Документацию https://laravel.com/docs/6.x/validation#manually -создание- валидаторы

ОБНОВЛЕНИЕ: 2 Если вам нужно разделить классы запросов, вы также можете сделать это следующим образом

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

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return array_merge([

            'name' => 'required|string',
            'lastname' => 'required|string',
            'user' => [
                'required',
                Rule::unique('users')->ignore($this),
            ],
            'email' => 'required|string|email|unique:users',
            'password' => 'required|string|confirmed',
            'headquarter_id' => 'required'

            //Validation of profile

            /** Validate of departments */
            'departments' => 'nullable|array',
        ], collect(array_map(function ($rules, $field): array {
            return ['departments.*.' . $field => $rules];
        }, (new StoreEventRequest)->rules()))
            ->collapse()
            ->toArray())
            ->toArray();
    }
}
0 голосов
/ 20 января 2020

Да, вы можете сделать это так

public function rules() {
        return [
            'name' => 'required|string',
            'lastname' => 'required|string',
            'user' => [ 'required', Rule::unique('users')->ignore($this), ],
            'email' => 'required|string|email|unique:users',
            'password' => 'required|string|confirmed',
            'headquarter_id' => 'required',
            //Validation of profile
            'profile.some_field' => 'required',
            //For array of objects
            'profile.*.some_field' => 'required',
        ];
    }
...