【问题标题】:Getting 200 response but not hitting controller store() mthod获得 200 响应但未命中控制器 store() 方法
【发布时间】:2020-03-24 14:21:34
【问题描述】:

我正在将刀片文件中的表单切换为使用 axios 发布的基于 vue 的表单。我收到 200 响应,但我没有在控制器中点击我的 store() 方法。我用原始刀片形式击中它。到目前为止,我尝试过的事情是手动添加 csrf 令牌,将标头更改为内容类型多部分,将发布数据更改为 JSON 字符串,以及更改 handleSubmit 以触发表单。这些似乎都没有任何效果。

我的刀片文件包含 vue 表单


@extends('layouts.app')

@section('content')
<div class="container">
    <create-post></create-post>
</div>

@endsection


createPost.vue


<template>
    <div class="container">
    <h4>create post</h4>
    <form @submit.prevent="handleSubmit" action='/p' enctype="multipart/form-data" method="post">
        <input type="hidden" name="_token" :value="csrf">
        <section v-if='step == 1'>
            <template v-for="(image, index) in images">
                <image-uploader-field
                    v-if='image_count >= index + 1'
                    v-bind:field='image'
                    v-bind:index='index'>
                </image-uploader-field>
            </template>
            <button
                v-if='image_count < 5'
                @click.prevent='addImage'>Add Another Image
            </button>

        </section>
        <section v-if='step == 2'>
            <h3>Auction Components</h3>
            <div>
                <label>starting bid $
                    <input type="number" min=".00" step=".01" v-model='starting_bid' placeholder='00.00' />
                </label>
            </div>
            <div>
                <label>bid increment $
                    <input type="number" min=".00" step=".01" v-model='bid_increment' placeholder='00.00'/>
                </label>
            </div>
            <div>
                end time
                    <datetime format="MM-DD-YYYY h:i:s" width="300px" v-model="end_time" ></datetime>

            </div>
            <div>
                <label>BIN $
                    <input type="number" min=".00" step=".01" v-model='bin' placeholder='00.00'/>
                </label>
            </div>
            <div>
                <label>snipe
                    <input type='checkbox' v-model='snipe'/>
                </label>
            </div>
            <div>
                <label v-if="snipe != false">snipe time
                    <input type="number" min="1" step="any" v-model='snipe_time' /> minutes
                </label>
            </div>
            <div>
                <label>auto remove bids
                    <input type='checkbox' v-model='autoremove_bids'/>
                </label>
            </div>
        </section>

        <section v-if='step == 3'>
            <h3>Write Caption</h3>
            <textarea
                v-model='caption'
                placeholder='type your message'
                class='form-control form-control-large'
                rows="4"
                cols="50">
            </textarea>
        </section>

        <section v-if='step == 4'>
            <h3>Preview</h3>
            <h4 v-if='caption !=null'>profilename: {{caption}}</h4>
            <h4 v-if='starting_bid !=null'>Starting Bid: ${{starting_bid}}</h4>
            <h4 v-if='bid_increment !=null'>Bid Increment: ${{bid_increment}}</h4>
            <h4 v-if='end_time !=null'>Auction ends at: {{end_time}}</h4>
            <h4 v-if='bin !=null'>BIN: ${{bin}}</h4>
            <h4 v-if='snipe_time !=null'>Snipe rule in effect: {{snipe_time}} minutes</h4>
        </section>

        <button
            v-if='step !== 1'
            @click.prevent='prevStep'>Previous</button>
        <button
            v-if='step !== totalsteps'
            @click.prevent='nextStep'
            v-text='nextText'></button>
        <button
            v-if='step == totalsteps'
            type='submit'>Post</button>
    </form>
    </div>
</template>
<style scoped>
    img{
        max-height: 36px;
    }
</style>
<script>
    import datetime from 'vuejs-datetimepicker';
    export default {
        components: { datetime },

        data: function () {
            return{
                image_count:1,
                max_uploads:5,
                totalsteps:4,
                step:1,
                images:[
                    {image_path:"", image_filters:[],},
                    {image_path:"", image_filters:[],},
                    {image_path:"", image_filters:[],},
                    {image_path:"", image_filters:[],},
                    {image_path:"", image_filters:[],},
                ],
                caption:null,
                starting_bid:null,
                bid_increment:null,
                end_time:null,
                bin:null,
                snipe:false,
                snipe_time:null,
                autoremove_bids:false,
                csrf: document.querySelector('meta[name="csrf-token"]').getAttribute('content'),

            }
        },
        computed: {
            nextText(){
                if(this.step == 3){
                    return 'Preview'
                } else {
                    return 'Next'
                }
            }

        },
        methods: {
            nextStep: function()
            {
                this.step++;
            },
            prevStep: function()
            {
                this.step--;
            },
            addImage: function()
            {
                this.image_count++
            },
            handleSubmit: function()
            {
                const post_data = Object.entries(this._data);
                axios.post('/p', post_data)

                  .then(function (response) {
                    console.log(response);
                  })
                  .catch(function (error) {
                    console.log(error);
                  });
            },
            onFileChange(e) {
                let files = e.target.files || e.dataTransfer.files;
                if (!files.length)
                    return;
                this.createImage(files[0]);
            },
            createImage(file) {
                 let reader = new FileReader();
                 let vm = this;
                 reader.onload = (e) => {
                     vm.image = e.target.result;
                 };
                 reader.readAsDataURL(file);
             },

            editImage(){
                alert('render image-editor here');
            },

        },

    }
</script>

我在 web.php 中发帖的路径


Route::get('/p/create', 'PostsController@create');
Route::post('/p', 'PostsController@store');

我的postsController 中的store 方法,我设置了一个console.log 只是为了查看如果我正在点击它,它看起来我不是


class PostsController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }
    public function create()
    {
        return view('posts/create');
    }

    public function store()
    {
        console.log('hit store method');
        //VALIDATES DATA
        $data = request()->validate([
            'caption' => 'required',
            'image1' => ['required', 'image',],
            'image2' => 'image',
            'image3' => 'image',
            'image4' => 'image',
            'image5' => 'image',
        ]);
        //CREATE IMAGES ARRAY AND UPLOADS TO S3
        $imageArray = [];
        $imageCount = 1;
        foreach($data as $key => $value){
            if (strpos($key, 'image') !== false) {
                $imagePath = request('image' . $imageCount)->store('uploads', 's3');
                $imageCount ++;
                array_push($imageArray, 'https://instagrizzle-development.s3.amazonaws.com/' . $imagePath);
            }
        }
        //Relational method HARDCODED profile
        auth()->user()->profiles[0]->posts()->create([
            'caption' => $data['caption'],
            'image' => json_encode($imageArray),
        ]);

        return redirect('/profile/' . auth()->user()->profiles[0]->id);
    }
}


添加

action='/p' enctype="multipart/form-data" method="post"

到表单标签似乎是多余的,但我想我会尝试一下。也不确定,但 axios 默认会自动添加 csrf 令牌吗?任何帮助,将不胜感激。提前致谢

这是我提交表单后得到的回复 response image

【问题讨论】:

  • 为什么你的 laravel 控制器中有一个console.log('hit store method');
  • 只是为了得到一些反馈,我确实在使用 store 方法
  • 我有一个 dd(response());前。但由于我的提交按钮上有 .prevent,我想我可能看不到它
  • 将其替换为return 'ok' ;console.log() 是 javascript,它在 php 中不起作用
  • 您可以尝试在 auth 中间件上方的控制器构造函数中使用 Log::info('') 或 dd()

标签: javascript php laravel vue.js laravel-blade


【解决方案1】:

您的中间件似乎有误

在你的控制器构造函数中使用 auth:api

见:https://laravel.com/docs/5.8/api-authentication#protecting-routes

您也可能在您的 axios 调用中遗漏了一些标头,您可以在

中进行验证

你的浏览器,如果它们都在那里的话。

同时为 csrf-token 验证您的 DOM

然后您可以使用包装 Axios 对象来设置您的默认标头。

像这样。 (例如保存到 api.js)

import Axios from 'axios'

export default() => {
  return Axios.create({
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
      'X-Requested-With': 'XMLHttpRequest',
      'X-CSRF-TOKEN' : document.head.querySelector('meta[name="csrf-token"]').content
    }
  })
}

然后将 axios 导入你的 vue 组件..

import Api from './api';

然后你可以像使用 axios 对象一样使用它

Api().request()

或者,如果您将通过所有 axios 调用使用这种单一的身份验证方式。您只需按照 laravel 在引导文件中启动的方式进行操作

像这样:

window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

【讨论】:

    【解决方案2】:

    将其替换为 return 'ok' ;。 console.log() 是 javascript,它在 php 中不起作用 – porloscerros Ψ 11 月 28 日 23:37

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-22
      • 2017-10-31
      • 1970-01-01
      • 2016-11-05
      • 1970-01-01
      • 2018-10-31
      相关资源
      最近更新 更多