Laravel проверка с хранилищем vuex всегда отвечает ошибка 422 - PullRequest
0 голосов
/ 14 июля 2020

Я новичок в Laravel Vue, напишите код для функции CURD, все работает нормально, кроме проверки на стороне сервера. Я получаю 422 с этим сообщением об ошибке: {"message": "Указанные данные недействительны.", "Errors": {"iso": ["Требуется поле iso."]}}

Запрос Полезная нагрузка: {страны: [,…]} страны: [,…] 0: {id: 2, iso: "UK", idd: "44", en_GB: "United Kingom", zh_HK: "UK", zh_CN: "UK", local: "UK", in_use: 1,…} 1: {id: 1, iso: "US", idd: "1", en_GB: "USA", zh_HK: "US", zh_CN: " US ", local:" US ", in_use: 1,…}

Среда: mariaDB 10 PHP 7.3.19, nodejs 12.16.3 composer 1.10.6 laravel 7.6.1 Homestead v10.8.1 virtualbox 6.1 Vue 2.6.11

связанные коды: countryManager. vue, CountrySwitch. vue, store / index. js, Amdin / CountryController. php, Country . php.

counryManger. vue

<template> 
    <v-container>
        <v-layout>
            <v-flex>
                <v-card class="mx-auto" >
                    <v-system-bar color="indigo darken-2" dark>
                    <v-spacer></v-spacer>
                
                    <v-icon>mdi-window-minimize</v-icon>
                
                    <v-icon>mdi-window-maximize</v-icon>
                
                    <v-icon>mdi-close</v-icon>
                    </v-system-bar>
                
                    <v-toolbar color="indigo" dark>
                        <v-app-bar-nav-icon></v-app-bar-nav-icon>
                    
                        <v-toolbar-title>Country table maintenance</v-toolbar-title>
                    
                        <v-spacer></v-spacer>
                    
                        <v-btn icon>
                            <v-icon>mdi-magnify</v-icon>
                        </v-btn>
                    </v-toolbar>
                    <v-card-text color="indigo darken-2" dark>
                        <div class="flex-table">
                        <div>ISO</div>
                            <div>English</div>
                            <div>Chinese Traditional</div>
                            <div>Chinese Simplified</div>
                            <div>Local Name</div>
                            <div>Idd Dialing Code</div>
                            <div>Remarks</div>
                            <div>
                                <v-icon @click="addCountry()">fa fa-plus-circle</v-icon>
                                <v-icon @click="trashedCountry()">fa fa-recycle</v-icon>
                            </div>
                        </div>
                        <div v-for="(country, index) in countries" :key="country.id" class="flex-table">
                            <div>
                                <div v-if="countryEditingId ==country.id">
                                    <v-text-field v-model="country.iso"></v-text-field>
                                </div>
                                <div v-else>
                                    {{country.iso}}
                                </div>
                            </div>
                            <div>
                                <div v-if="countryEditingId ==country.id">
                                    <v-text-field v-model="country.en_GB" ></v-text-field>
                                </div>
                                <div v-else>
                                    {{country.en_GB}}
                                </div>
                            </div>
                            <div>
                                <div v-if="countryEditingId ==country.id">
                                    <v-text-field v-model="country.zh_HK" ></v-text-field>
                                </div>
                                <div v-else>
                                    {{country.zh_HK}}
                                </div>
                            </div>
                            <div>
                                <div v-if="countryEditingId ==country.id">
                                    <v-text-field v-model="country.zh_CN" ></v-text-field>
                                </div>
                                <div v-else>
                                    {{country.zh_CN}}
                                </div>
                            </div>
                            <div>
                                <div v-if="countryEditingId ==country.id">
                                    <v-text-field v-model="country.local" ></v-text-field>
                                </div>
                                <div v-else>
                                    {{country.local}}
                                </div>
                            </div>
                            <div>
                                <div v-if="countryEditingId ==country.id">
                                    <v-text-field v-model="country.idd" ></v-text-field>
                                </div>
                                <div v-else>
                                    {{country.idd}}
                                </div>
                            </div>
                            <div>
                                <div v-if="countryEditingId ==country.id">
                                    <v-text-field v-model="country.remarks"></v-text-field>
                                </div>
                                <div v-else>
                                    {{country.remarks}}
                                </div>
                            </div>
                            
                            <div>
                                <div v-if="!country.deleted_at">
                                    <div v-if="countryEditingId ==country.id">
                                        <v-btn x-small @click="saveCountries(country)">Save</v-btn>
                                    </div>
                                    <div v-else>
                                        <v-btn x-small @click="setToEditing(country)">Edit</v-btn>
                                    </div>
                                </div>
                                <div  v-if="!country.deleted_at">
                                    <div v-if="countryEditingId ==country.id">
                                        <v-btn x-small @click="resetCountries()">Cancel</v-btn>
                                    </div>
                                    <div v-else>
                                        <v-btn x-small @click="removeCountries(index)">Remove</v-btn>
                                    </div>
                                </div>
                                <div v-else>
                                    <v-btn x-small @click="restoreCountries(index)">Restore</v-btn>
                                </div>
                                
                            </div>
                        </div>
                    </v-card-text>
                    <v-spacer></v-spacer>
                    <v-card-subtitle class="grey">
                        <div class="card-footer text-muted">{{ feedback }}</div>
                        <div v-if="validationErrors"class="card-footer text-muted">{{ validationErrors }}</div>
                    </v-card-subtitle>
                </v-card>
            </v-flex>
        </v-layout>
    </v-container>
</template>

<script>
    export default {
        data(){
            return {
                countryEditingId:''
            };
        },
        computed: {
            validationErrors(){
                return this.$store.state.validationErrors;
            },
            countries(){
                return this.$store.state.countries;
            },
            feedback(){
                return this.$store.state.feedback;
            }
        },
        methods: {
            resetCountries(){
                this.countryEditingId = "";
                this.$store.dispatch('resetCountries');
            },
            setToEditing(country){
                this.countryEditingId = country.id;
            },
            addCountry(){
                this.$store.commit('ADD_COUNTRIES',{
                    id:'',
                    iso:'',
                    en_GB:'',
                    zh_HK:'',
                    zh_CN:'',
                    idd:'',
                    remarks:''
                });
            },
            saveCountries(){
                this.countryEditingId='';
                this.$store.dispatch('saveCountries');
               
            },
            updateCountries($event, property, index){
                this.countryEditingId='';
                this.$store.commit('UPDATE_COUNTRIES',{
                    index,
                    property,
                    value:$event.target.value
                });
            },
        }
    }
</script>
<style lang="scss" scoped>
.flex-table {
    display: grid;
    grid-template-columns: repeat(auto-fill,12%);
    padding:5px;
    &:nth-of-type(2n) {
        background-color: #dedede;
    }
    .actions {
        * {
            padding-right: 10px;
        }
    }
}
</style>

countrySwitch. vue

<template>
<v-app>
  
    <!-- <router-link :to="{name: 'country'}">Country</router-link> -->
    <router-view></router-view>
  </v-app>
</template>

<script>
    import VueRouter from 'vue-router';   
    import CountryManager from './CountryManager.vue';
    import store from '../store';
    Vue.use(VueRouter);

    export default {
        store,
        props: ['countries'],
        created() {
            this.$store.commit('SET_COUNTRIES', _.cloneDeep(this.countries));
        },
        router: new VueRouter({
            mode: 'history',
            base: 'country',
            routes: [
                {
                    path: '/admin/country',
                    name: 'country',
                    component: CountryManager
                },
                {
                    path: '/',
                    redirect: {name: 'country'}
                },
            ]
        })
    }
</script>

store / index. js

import Vue from 'vue';
import Vuex from 'vuex';
import Axios from 'axios';

Vue.use(Vuex);

export default new Vuex.Store({
    state:{
        countries:[],
        feedback: '',
        validationErrors:''
    },
    mutations :{
        SET_COUNTRIES(state, countries){
            state.countries = countries;
        },
        ADD_COUNTRIES(state, countries){
            state.countries.push(countries);
        },
        REMOVE_COUNTRIES(state, index){
            state.countries.splice(index, 1);
        },
        UPDATE_COUNTRIES(state,{index, property, value}){
            state.countries[index][property] = value;
        },
        SET_FEEDBACK(state, feedback){
            state.feedback = feedback;
        },
        SET_ERRORS(state, validationErrors){
            state.validationErrors = validationErrors;
        },
    },
    actions:{
        saveCountries({commit, state}){
            axios.post('/api/countries/upsert',{
                countries: state.countries,
            })
            .then ((res)=>{
                if(res.status == 200){
                    commit('SET_FEEDBACK','Changes Saved');
                    setTimeout(()=> commit('SET_FEEDBACK',''), 5000);
                    commit('SET_COUNTRIES', res.data.countries);
                }
            })
            .catch((error)=>{
                commit('SET_FEEDBACK','Error: Unable update / insert records');
                commit('SET_ERRORS', error.response);
            });
        },
        resetCountries({commit}){
            axios.get('/api/countries/list')
            .then ((res)=>{
                if(res.status == 200){
                    commit('SET_FEEDBACK','Action Cancelled');
                    setTimeout(()=> commit('SET_FEEDBACK',''), 5000);
                    commit('SET_COUNTRIES', res.data.countries);
                };
            });
        },
        removeCountries({commit, state}, index){
            let id = state.countries[index].id;
            if (id > 0){
                axios.delete('/api/countries/'+id)
                    .then((res)=>commit('REMOVE_COUNTRIES',index));
            }
            commit ('REMOVE_COUNTRIES', index)
        },
        restoreCountries({commit, state}, index){
            let id = state.countries[index].id;
            // console.log(id);
            if (id > 0){
                return axios.put('/api/countries/',{id})
                // .then((res)=>console.log(res.status))
                .then ((res)=>{
                    if(res.status == 200){
                        // console.log(res);
                        commit('SET_FEEDBACK','Record Restored');
                        setTimeout(()=> commit('SET_FEEDBACK',''), 5000);
                        commit('SET_COUNTRIES', res.data.countries);
                    }
                });
            }
        },

    }

});

Amdin / CountryController. php

<?php

namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\country;
use Illuminate\Http\Request;

class CountryController extends Controller
{
    /**
     * Update and Insert records
     *
     * @return \Illuminate\Http\Response
     */
    public function upsert(Request $request, country $countries)
    {
        $this->authorize('restore','App\Country');
        $this->validate($request, ['iso' => 'required']);
        $countries = $request->post('countries');
        foreach ($countries as $cou){
            if ($cou['id']){              
                Country::where('id', $cou['id'])->update($cou);
            }else{
               
                Country::create($cou);
            }
        }
        $countries = Country::orderBy('en_GB')->get();
        return  ['countries'=> $countries];
    }
   
}

Страна. php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Country extends Model
{
    use SoftDeletes;
    protected $guarded = [];
    
}

Ответы [ 2 ]

0 голосов
/ 14 июля 2020

этот код будет работать только тогда, когда вы проверите одну страну для каждого сообщения:

 $this->validate($request, ['iso' => 'required']);

Но вы сохраняете n стран, поэтому вам нужно будет проверить массив:

$this->validate($request, ['countries.*.iso' => 'required']);
0 голосов
/ 14 июля 2020

проблема в ваших правилах проверки. Когда вы пишете

$this->validate($request, ['iso' => 'required']);

, это означает, что ваш запрос требует, чтобы поле «iso» было проверено, а в вашем сообщении

 axios.post('/api/countries/upsert',{
            countries: state.countries,
 })

у вас есть только опора «страны» и « iso "считается пустым, поэтому ваши обязательные правила всегда отклоняются.

Если вы пытаетесь проверить, что каждая страна в массиве ваших стран должна иметь обязательное поле" iso ", вы должны проверить, как проверять массивы здесь Laravel Проверка массивов

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...