Laravel8 | Vuex:POST 错误 500(内部服务器错误)

Laravel8 | Vuex: POST error 500 (Internal Server Error)

过去 2 个月我一直在学习 Vue 和 Laravel,最近我开始从事一个项目,以便应用我到目前为止学到的所有知识。我成功地设置了几个 GET 和 POST 路由,但由于某种原因,这个请求一直失败。 我正在尝试使用 Vuex、Laravel 和 Axios 设置一个简单的 POST 请求,但我一直收到 500(内部服务器错误),我不确定是什么原因造成的。我觉得可能是模型设置不正确,如果我输出控制器接收到的数据,它看起来是正确的,但是当我实例化模型并将数据保存到数据库时,我得到了错误。

我非常感谢对我的代码的任何帮助或反馈,因为我处于学习曲线的早期阶段,并且我确信有些事情可以优化。

路线:

//StreamingProviders
Route::get('/api/all-streaming-providers', [StreamingProviderController::class, 'getAllStreamingProviders']);
Route::post('/api/add-streaming-providers', [StreamingProviderController::class, 'addStreamingProviders']);

控制器:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Repository\Dictionaries\StreamingProvidersList;
use App\Models\StreamingProvider;

class StreamingProviderController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }

    public function getAllStreamingProviders()
    {
        $streamingProviders = StreamingProvidersList::$map;
        
        return response()->json([
            'allProviders' => $streamingProviders
        ]);
    }

    public function addStreamingProviders(Request $request, StreamingProvider $userStreamingProviders)
    {
        $user = auth()->user();
        $data = $request->all();
    
        $userStreamingProviders = new StreamingProvider();
        $userStreamingProviders->user_id = $user['id'];
        $userStreamingProviders->Netflix = $request->input('Netflix');
        $userStreamingProviders->Amazon_Prime_Video = $request->input('Amazon Prime Video');
        $userStreamingProviders->Sky_Ticket = $request->input('Sky Ticket');
        $userStreamingProviders->Disney_Plus = $request->input('Disney Plus');
        $userStreamingProviders->HBO_Video = $request->input('HBO Video');
        $userStreamingProviders->save();

        return response()->json([
            'streamingProviders' => $userStreamingProviders            
        ]);
    }
}

FormComponent.vue

<template>
    <div class="container">
        <div class="row justify-content-center">
            <div class="card">
                <div class="card-header">
                    <h2>Select your streaming country</h2>
                </div>
                <form @submit.prevent="updateUserDetails()">
                    <div class="card-body">                   
                        <div class="form-control">
                            <select class="selectpicker" id="countryList">
                                <option v-for="(value, name) in getCountriesList" :key="name" :value="name">
                                    {{ value }}
                                </option>
                            </select>
                        </div>   
                        <div v-for="(value, name) in getAllStreamingProviders" :key="name" class="form-check">
                            <input v-model="streamingProviders[value]"
                                type="checkbox"
                                :id="name"
                                :value="value"
                                :name="streamingProviders[value]"
                                class="form-check-input" />
                            <label>{{ value }}</label>
                        </div>
                    </div>
                    <div class="card-footer">
                        <button type="submit" class="btn btn-success center-text">Save</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
</template>

<script>
import { mapGetters } from 'vuex';
import router from '../../routes/index';

export default {
    name: 'edituserdetails',
    data() {
        return {
            value: '',
            streamingProviders: {
                'Netflix': false,
                'Amazon Prime Video': false,
                'Disney Plus': false,
                'HBO Video': false,
                'Sky Ticket': false
            }
        }
    },
    created() {
        this.$store.dispatch('getCountriesList'),
        this.$store.dispatch('getAllStreamingProviders')
    },
    methods: {
        updateUserDetails() {
            const country = {
                'id': $('#countryList').children("option:selected").val(),
                'name': $('#countryList').children("option:selected").text()
            };
            this.$store.dispatch('updateUserStreamingProviders', this.streamingProviders);

            this.$store.dispatch('updateCountry', country).then(() => {
                router.push('/user-settings');
            });
        }
    },
    computed: {
        ...mapGetters(['getCountriesList', 'getAllStreamingProviders']),
    }
}
</script>

Vuex 商店:

import axios from "axios";

const state = {
    userName: "",
    country: "",
    countriesList: {},
    allStreamingProviders: {},
    userStreamingProviders: []
};

const mutations = {
    UPDATE_USERNAME(state, payload) {
        state.userName = payload;
    },
    GET_COUNTRIES_LIST(state, payload) {
        state.countriesList = payload;
    },
    UPDATE_COUNTRY(state, payload) {
        state.country = payload;
    },
    GET_ALL_STREAMING_PROVIDERS(state, payload) {
        state.allStreamingProviders = payload;
    },
    UPDATE_STREAMING_PROVIDERS(state, payload) {
        state.userStreamingProviders = payload;
    }
};

const actions = {
    updateUserData({ commit }) {
        axios.get("/api/user").then(response => {
            commit("UPDATE_USERNAME", response.data.name);
            commit("UPDATE_COUNTRY", response.data.country);
        });
    },
    getCountriesList({ commit }) {
        axios.get("/api/countries-list").then(response => {
            commit("GET_COUNTRIES_LIST", response.data.list);
        });
    },
    updateCountry({ commit }, country) {
        axios
            .post("/api/update-country", country)
            .then(response => {
                commit("UPDATE_COUNTRY", response.data.country);
            })
            .catch(err => {
                console.log(err);
            });
    },
    getAllStreamingProviders({ commit }) {
        axios.get("/api/all-streaming-providers").then(response => {
            commit("GET_ALL_STREAMING_PROVIDERS", response.data.allProviders);
        });
    },
    updateUserStreamingProviders({ commit }, streamingProviders) {
        axios
            .post("/api/add-streaming-providers", streamingProviders)
            .then(response => {
                commit(
                    "UPDATE_STREAMING_PROVIDERS",
                    response.data.streamingProviders
                );
            })
            .catch(err => {
                console.log(err);
            });
    }
};

const getters = {
    getUserName: state => state.userName,
    getCountry: state => state.country,
    getCountriesList: state => state.countriesList,
    getAllStreamingProviders: state => state.allStreamingProviders
};

const userStore = {
    state,
    mutations,
    actions,
    getters
};

export default userStore;

流媒体提供商模型:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class StreamingProvider extends Model
{
    use HasFactory;

     /**
     * Attributes that are mass assignable
     * 
     * @var array
     */
    protected $fillable = ['user_id', 'Netflix', 'Amazon_Prime_Video', 'Sky_Ticket', 'Disney_Plus', 'HBO_Video'];

    protected $table = 'streaming_provider';

    protected $cast = [
        'Netflix' => 'boolean',
        'Amazon_Prime_Video' => 'boolean',
        'Sky_Ticket' => 'boolean',
        'Disney_Plus' => 'boolean',
        'HBO_Video' => 'boolean'
    ];

    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

在将数据保存到数据库之前是否必须转换数据? 布尔属性是否被视为 $fillable ??

迁移:

<?php

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

class StreamingProvidersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('streaming_provider', function (Blueprint $table) {
            $table->id();
            $table->string('user_id');
            $table->boolean('Netflix')->default(0);
            $table->boolean('Amazon_Prime_Video')->default(0);
            $table->boolean('Sky_Ticket')->default(0);
            $table->boolean('Disney_Plus')->default(0);
            $table->boolean('HBO_Video')->default(0);
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('streaming_provider');
    }
}

Laravel.log:

[2021-10-27 09:12:39] local.ERROR: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'updated_at' in 'field list' (SQL: insert into `streaming_provider` (`user_id`, `Netflix`, `Amazon_Prime_Video`, `Sky_Ticket`, `Disney_Plus`, `HBO_Video`, `updated_at`, `created_at`) values (1, 1, 1, 0, 0, 0, 2021-10-27 09:12:39, 2021-10-27 09:12:39)) {"userId":1,"exception":"[object] (Illuminate\Database\QueryException(code: 42S22): SQLSTATE[42S22]: Column not found: 1054 Unknown column 'updated_at' in 'field list' (SQL: insert into `streaming_provider` (`user_id`, `Netflix`, `Amazon_Prime_Video`, `Sky_Ticket`, `Disney_Plus`, `HBO_Video`, `updated_at`, `created_at`) values (1, 1, 1, 0, 0, 0, 2021-10-27 09:12:39, 2021-10-27 09:12:39)) at C:\xampp\htdocs\laravel_vue\Fullstack_Project_Movie_III\vendor\laravel\framework\src\Illuminate\Database\Connection.php:703)
[previous exception] [object] (PDOException(code: 42S22): SQLSTATE[42S22]: Column not found: 1054 Unknown column 'updated_at' in 'field list' at C:\xampp\htdocs\laravel_vue\Fullstack_Project_Movie_III\vendor\laravel\framework\src\Illuminate\Database\Connection.php:486)


谢谢大家!!

出现此错误是因为迁移中缺少 $table->timestamps();,因此您必须添加它,Laravel 会自动为您创建 updated_atcreated_at 列。 对于 laravel 中的每个条目和更新,它会自动为这些列分配值,因此很明显,当它们从数据库中丢失时,您会收到此错误。

之后,您的迁移将如下所示:

`Schema::create('streaming_provider', function (Blueprint $table) {
        $table->id();
        $table->string('user_id');
        $table->boolean('Netflix')->default(0);
        $table->boolean('Amazon_Prime_Video')->default(0);
        $table->boolean('Sky_Ticket')->default(0);
        $table->boolean('Disney_Plus')->default(0);
        $table->boolean('HBO_Video')->default(0);
        $table->timestamps();
    });`