@iwantit

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Vue.js + Laravel8でVue側のログアウト処理が上手くいかない

【開発環境】
Windows 10 HOME
PHP 7.4.7
laravel/framework: ^8.2,
vue": "^2.5.17",

解決したいこと

Vue.js + Laravelの勉強で下記の記事を見て
ローカルで開発しています。
Vue.js + LaravelでシンプルなSPA構築チュートリアル:概要編

これにログイン機能をつけているのですが、
ログイン後のタスク一覧のヘッダー部分に
「ログアウト」のボタンつけてログアウト処理をしたいのですがわかりません。

簡単に構造を説明すると
ヘッダー部分に
・一覧ページボタン
・新規登録ページボタン
・ログアウトボタン

を作って各ページで
ヘッダー部分を読み込んてログアウト処理を実装しています。

ログイン後の一覧ページでは正常にログアウト処理が出来ますが
その他の「create」ページではログアウト処理が出来ず
F12で見ると下記のエラーが出ています。

POST http://localhost:8000/tasks/api/logout 405 (Method Not Allowed)

ステータスコードが「405」という事は
ログアウト処理が送信されますが
サーバーがその要求をHTTPメソッドとして受信したものの、拒否してしまった状況を示しています。

resources\js\components\HeaderComponent.vue
<template>
    <div class="container-fluid bg-dark mb-3">
        <div class="container">
            <nav class="navbar navbar-dark">
                <span class="navbar-brand mb-0 h1">Vue Laravel SPA</span>

                <!-- Authenticated -->
                <div v-if="user">
                    <router-link v-bind:to="{name:'task.list'}">
                        <button class="btn btn-success">List</button>
                    </router-link>
                    <router-link v-bind:to="{name:'task.create'}">
                        <button class="btn btn-success">ADD</button>
                    </router-link>

                    <button type="button" class="btn btn-danger" @click="logout">Logout</button>

                </div>

                <!-- Gusst -->
                <div v-else>
                    <router-link v-bind:to="{name:'login'}">
                        <button class="btn btn-success">login</button>
                    </router-link>
                </div>

            </nav>
        </div>
    </div>
</template>

<script>
export default {
    data() {
        return {
            user: ""
        };
    },
    mounted() {
        axios.get("/api/user").then(response => {
            this.user = response.data;
        });
    },
    methods: {
        logout() {
            axios
                .post("api/logout")
                .then(response => {
                    console.log(response);
                    localStorage.removeItem("auth");
                    this.$router.push("/login");
                })
                .catch(error => {
                    console.log(error);
                });
        }
    },

};
</script>

下記がヘッダーを読み込んでいる
新規登録画面です。

resources\js\components\TaskCreateComponent.vue
<template>
    <div>
        <HeaderComponent></HeaderComponent>

        <div class="container">
            <div class="row justify-content-center">
                <div class="col-sm-6">
                    <form v-on:submit.prevent="submit">
                        <div class="form-group row">
                            <label for="title" class="col-sm-3 col-form-label">Title</label>
                            <input type="text" class="col-sm-9 form-control" id="title" v-model="task.title">
                        </div>
                        <div class="form-group row">
                            <label for="content" class="col-sm-3 col-form-label">Content</label>
                            <input type="text" class="col-sm-9 form-control" id="content" v-model="task.content">
                        </div>
                        <div class="form-group row">
                            <label for="person-in-charge" class="col-sm-3 col-form-label">Person In Charge</label>
                            <input type="text" class="col-sm-9 form-control" id="person-in-charge" v-model="task.person_in_charge">
                        </div>
                        <button type="submit" class="btn btn-primary">Submit</button>
                    </form>
                </div>
            </div>
        </div>
    </div>        
</template>

<script>
import HeaderComponent from "./HeaderComponent.vue"

    export default {
        components: { 
            HeaderComponent
        },

        data: function () {
            return {
                task: {}
            }
        },
        methods: {
            submit() {
                axios.post('/api/tasks', this.task)
                    .then((res) => {
                        this.$router.push({name: 'task.list'});
                    });
            },


        }
    }
</script> 
resources\js\router.js

import Vue from "vue";
import VueRouter from "vue-router";

import HeaderComponent from "./components/HeaderComponent";

import TaskCreateComponent from "./components/TaskCreateComponent";
import TaskEditComponent from "./components/TaskEditComponent";

import TaskListComponent from "./components/TaskListComponent";
import TaskShowComponent from "./components/TaskShowComponent";

import login from "./components/login.vue";
import about from "./components/about.vue";

Vue.use(VueRouter);
Vue.component('header-component', HeaderComponent);
//Vue.component('header-component2', HeaderComponent2);


const router = new VueRouter({
    mode: "history",
    routes: [

                {
            path: '/tasks',
            name: 'task.list',
            component: TaskListComponent,
            meta: { authOnly: true }
        },

        {
            path: '/tasks/create',
            name: 'task.create',
            component: TaskCreateComponent,
            meta: { authOnly: true }
        },
        /*   */
        {
            path: '/task/:taskId/edit',
            name: 'task.edit',
            component: TaskEditComponent,
            meta: { authOnly: true },
            props: true
        },

        {
            path:'/task/:taskId',
            name:'task.show',
            component: TaskShowComponent,
            meta: { authOnly: true },
            props: true
        },

        {
            path: "/about",
            name: "about",
            component: about,
            meta: { authOnly: true }
        },

        {
            path: "/login",
            name: "login",
            component: login,
            meta: { guestOnly: true }
        },

        {
            path: "/",
            name: "login",
            component: login,
            meta: { guestOnly: true }
        },


    ]
});

function isLoggedIn() {
    return localStorage.getItem("auth");
}

router.beforeEach((to, from, next) => {
    if (to.matched.some(record => record.meta.authOnly)) {
        if (!isLoggedIn()) {
            next("/login");
        } else {
            next();
        }
    } else if (to.matched.some(record => record.meta.guestOnly)) {
        if (isLoggedIn()) {
            next("/tasks");
        } else {
            next();
        }
    } else {
        next();
    }
});

export default router;
routes\api.php
<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
    return $request->user();
});

Route::post('/login', 'App\Http\Controllers\LoginController@login');
Route::post('/logout', 'App\Http\Controllers\LoginController@logout');


Route::get('/tasks', 'App\Http\Controllers\TaskController@index');
Route::post('/tasks', 'App\Http\Controllers\TaskController@store');
Route::get('/tasks/{task}', 'App\Http\Controllers\TaskController@show');
Route::put('/tasks/{task}', 'App\Http\Controllers\TaskController@update');
Route::delete('/tasks/{task}', 'App\Http\Controllers\TaskController@destroy');


routes\web.php
<?php

use Illuminate\Support\Facades\Route;


Route::get('{any}', function () {
    return view('index');
})->where('any', '.*');

Auth::routes();

何か心当たりがある方、
解決方法を教えて下さい。

0 likes

2Answer

 methods: {
        logout() {
            axios
                .post("/api/logout") //<--  api/logout を /api/logout に変更

/api/logoutに変更すれば治ると思います。

php artisan route:listでラウトのルート(パスpath)やメソッド(GET、POSTなど)を確認することができます。

1Like

Comments

  1. @iwantit

    Questioner

    @skys215 様

    コメントありがとうございます。
    ログアウト処理が無事出来ました。

Comments

  1. @iwantit

    Questioner

    コメントありがとうございます。

    下記のソースを追加しました。

    routes\web.php
    routes\api.php
    resources\js\router.js

Your answer might help someone💌