iT邦幫忙

2022 iThome 鐵人賽

DAY 5
0
Modern Web

LV的全端開發體驗系列 第 5

Day05 規劃路由、頁面、控制器

  • 分享至 

  • xImage
  •  

像我這種一人全端開發者,有些工夫能省就省,所以沒有需求文件,開發文件什麼的,心之所向,功能之所在;

雖然可以隨興的開發,但如果真的都沒個規劃,也常常做到後期會有難以收尾的狀況,所以我自己習慣在建立好專案的時候,會先把核心功能需要的頁面及 Controller, Model 都先順過一次,沒有資料也沒關係,用簡單的連結,讓畫面流程可以先走一邊,大概路由會是如何的,需要那些控制器或資源什麼的,都會在這步驟先有點東西出來,將來在進行正式開發時,隨時會知道還有那些畫面或是有那個控制器還沒處理。

簡單來說,我是說我的開發文件直接寫在我的網站上。

前後台畫面

先來建立前後台,就是把原本的 welcome 和 Dashboard 拿來改一下就可以了

Welcome => Home

<script setup>
import { Head, Link } from '@inertiajs/inertia-vue3';

defineProps({
    canLogin: Boolean,
    canRegister: Boolean,
})
</script>

<template>
    <!--inertia的HEAD組件可以用來改變瀏灠器分頁上的標籤文字(title)-->
    <Head title="學科測驗系統" />
    
    <!--這一段是註冊登入用的,將來可以改成sticky的標題功能列-->
    <div class="relative flex items-top justify-center min-h-screen 
                bg-gray-100 dark:bg-gray-900 sm:items-center sm:pt-0">
        <div v-if="canLogin" 
             class="hidden fixed top-0 right-0 px-6 py-4 sm:block">
            <Link v-if="$page.props.auth.user" 
                  :href="route('dashboard')" 
                  class="text-sm text-gray-700 dark:text-gray-500 underline">
                Dashboard
            </Link>

            <template v-else>
                <Link :href="route('login')" 
                      class="text-sm text-gray-700 dark:text-gray-500 underline">
                    Log in
                </Link>

                <Link v-if="canRegister" 
                      :href="route('register')" 
                      class="ml-4 text-sm text-gray-700 dark:text-gray-500 underline">
                    Register
                </Link>
            </template>
        </div> 
        <!--前台主要內容區域-->
        <div>
            <ul>
                <li>可以選擇學科別</li>
                <li>可以選擇測驗或是練習</li>
                <li>可以單純查看題庫</li>
            </ul> 
        </div>
    </div>
</template>

Dashboard => Backstage

<script setup>
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout.vue';
import { Head } from '@inertiajs/inertia-vue3';
</script>

<template>
    <Head title="管理中心" />

    <AuthenticatedLayout>
        <template #header>
            <h2 class="font-semibold text-xl text-gray-800 leading-tight">
                管理中心
            </h2>
        </template>

        <div class="py-12">
            <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
                <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
                    <div class="p-6 bg-white border-b border-gray-200">
                        <ul>
                            <li>可以新增題庫</li>
                            <li>可以編輯試卷</li>
                            <li>可以刪除題庫/試卷</li>
                            <li>可以查看測驗成績</li>
                            <li>可以建立/編輯/刪除群組</li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>
    </AuthenticatedLayout>
</template>

這兩個檔案的路由是在 \route\web.php 中控制的,所以我們也要同時改一下web.php,不然會抓不到正確的頁面,原本的回傳參數中用不到的我們就刪除不用了,留下登入和註冊兩個就可以了:

web.php

Route::get('/', function () {
    return Inertia::render('Home', [
        'canLogin' => Route::has('login'),
        'canRegister' => Route::has('register'),
    ]);
});

Route::get('/backstage', function () {
    return Inertia::render('Backstage');
})->middleware(['auth', 'verified'])->name('dashboard');

不過改完後重新登入時會發現錯誤:

這是因為breeze預設登入成功後會把使用者導到 /dashboard 但我改了這個路由,所以發生了原本的路由找不到頁面的問題,因此我們要連帶的去修正後台的路由導向,我們移動到Controller去;

App\Http\Controllers\Auth 目錄中我們會看到一堆檔案,這些都是breeze幫我們建立的會員系統相關控制器,其中很多程式都提到了,如果認證成功,會把使用者導去一個地方:

public function store(LoginRequest $request)
{
    $request->authenticate();
    $request->session()->regenerate();
    return redirect()->intended(RouteServiceProvider::HOME);
}

這個函式的意思是說,如果登入成功了,會建立一個session,然後把使用者導向他原本登入後該去的地方,比如登入成功後應該是去個人頁面。

所以我們來查查看這個 RouteServiceProvider::HOME 的位置到底是那裏,移動到 \App\Provider\RouteServiceProvider.php

class RouteServiceProvider extends ServiceProvider
{  
    public const HOME = '/dashboard';
......略

我們看到常數HOME原來被定義為 /dashboard 所以登入成功後的導向 HOME 這個動作,其實都是導向 dashboard,知道這個用法後,以後有些常用的路由就可以來這裏統一定義,免得將來要修改時要每個函式都去改。

'/dashboard' 改成 '/backstage' 後再重新登入,就會導向正確的後台頁面了。

Controller

但是我們不可能在 web.php 中寫邏輯,所以要建立起controller來,讓請求進來後,到對應的Controller去執行;

下指令來建立Controller:

php artisan make:controller HomeController
php artisan make:controller BackstageController

Controller的命名,依照你的系統規劃來做就可以了,有人喜歡和Model一樣的名子,有人喜歡依功能別來命名,其實都可以,只要團隊溝通好就行了,而我這種一人團隊,就更隨興了,目前只是暫時由前端先做起,等後端的Model建立後,這些Controller可能會再來改名成更適合的樣子。

建立完 Controller 後,接著就是把頁面繪製的程式碼搬動,讓 web.php 日後只做單純的路由工作就好了

HomeController.php

<?php
namespace App\Http\Controllers;

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

class HomeController extends Controller
{
    function home() {
        return Inertia::render('Home', [
            'canLogin' => Route::has('login'),
            'canRegister' => Route::has('register'),
        ]);
    }
}

BackstageController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Inertia\Inertia;

class BackstageController extends Controller
{
    function controlPanel() {
        return Inertia::render('Backstage');
    }
}

web.php

Route::get('/', [HomeController::class,'home']);

Route::get('/backstage', [BackstageController::class,'controlPanel'])
       ->middleware(['auth', 'verified'])
       ->name('dashboard');

接著我們要來改一下原本的路由名稱 dashboard ,這是為了方便使用路由,所以給了這個命名的功能,我們現在把 web.php 中的dashboard命名改成backstage,並且要巡一遍前後端的程式碼中有沒有使用到這個名字的,都要改一遍。

Route::get('/backstage', [BackstageController::class,'controlPanel'])
       ->middleware(['auth', 'verified'])
       ->name('backstage');

resources\js\Pages\Home.vue

<script setup>
import { Head, Link } from '@inertiajs/inertia-vue3';

defineProps({
    canLogin: Boolean,
    canRegister: Boolean,
})
</script>

<template>
<!--inertia的HEAD組件可以用來改變瀏灠器分頁上的標籤文字(title)-->
<Head title="學科測驗系統" />

<!--這一段是註冊登入用的,將來可以改成sticky的標題功能列-->
<div class="relative flex items-top justify-center 
            min-h-screen bg-gray-100 dark:bg-gray-900 sm:items-center sm:pt-0">
    <div v-if="canLogin" class="hidden fixed top-0 right-0 px-6 py-4 sm:block">

        <!--這裏的路由要改成backstage-->
        <Link v-if="$page.props.auth.user" 
             :href="route('backstage')" 
             class="text-sm text-gray-700 dark:text-gray-500 underline">
                 管理中心
        </Link>

        <template v-else>
        <Link :href="route('login')" 
              class="text-sm text-gray-700 dark:text-gray-500 underline">
                  Log in
        </Link>

        <Link v-if="canRegister" 
              :href="route('register')" 
              class="ml-4 text-sm text-gray-700 dark:text-gray-500 underline">
                  Register
        </Link>
        </template>
    </div> 
    <!--前台主要內容區域-->
    <div>
        <ul>
            <li>可以選擇學科別</li>
            <li>可以選擇測驗或是練習</li>
            <li>可以單純查看題庫</li>
        </ul> 
    </div>
</div>
</template>

這個 AuthenticatedLayout 組件是用來定義登入成功後的頁面基本版型,同時也包含了登出連結,使用了一個 slot 讓使用者可以自行設計自己的內容,同時RWD也做好了;

我們一樣把當中的 dashboard 名字都改成backstage

resources\js\Layouts\AuthenticatedLayout.vue

<script setup>
import { ref } from 'vue';
import ApplicationLogo from '@/Components/ApplicationLogo.vue';
import Dropdown from '@/Components/Dropdown.vue';
import DropdownLink from '@/Components/DropdownLink.vue';
import NavLink from '@/Components/NavLink.vue';
import ResponsiveNavLink from '@/Components/ResponsiveNavLink.vue';
import { Link } from '@inertiajs/inertia-vue3';

const showingNavigationDropdown = ref(false);
</script>

<template>
.....略
<nav class="bg-white border-b border-gray-100">
    <!-- Primary Navigation Menu -->
    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
        <div class="flex justify-between h-16">
            <div class="flex">
                <!-- Logo -->
                <div class="shrink-0 flex items-center">

                    <!--這裏的路由要改成backstage-->
                    <Link :href="route('backstage')">
                        <ApplicationLogo class="block h-9 w-auto" />
                    </Link>
                </div>

                <!-- Navigation Links -->
                <div class="hidden space-x-8 sm:-my-px sm:ml-10 sm:flex">

                    <!--這裏的路由要改成backstage-->
                    <NavLink :href="route('backstage')" 
                             :active="route().current('backstage')">
                        管理中心
                    </NavLink>
                </div>
            </div>
            .....略
        </div>
    </div>

    <!-- Responsive Navigation Menu -->
    <div :class="{'block': showingNavigationDropdown, 
                  'hidden': ! showingNavigationDropdown}" 
         class="sm:hidden">
        <div class="pt-2 pb-3 space-y-1">
            <!--這裏的路由要改成backstage-->
            <ResponsiveNavLink :href="route('backstage')" 
                               :active="route().current('backstage')">
                管理中心
            </ResponsiveNavLink>
        </div>
        .....略
    </div>
</nav>
.....略
</template>

透過這個步驟,我們大致的巡了一次 Breeze 套件的主要功能及相關的檔案,看過一次可以修改的地方,也做了一些初步的變更,對於 laravel+Vue 的整合運用算是踏出了成功的第一步,當初是看著這些別人寫好的套件去了解整個系統的運作模式,之後要做更多自己想要的功能時,就可以很得心應手了。

這邊的修改只是測試而已,,我們在確認這樣的搬動及調整是可行後,接下來就是針對這個專案真正的需求下去做改動了:

因為會有不同的身份登入,所以目前在 breeze 中寫死的 Dashboard 文字,到時要想個辦法可以依照登入者的身份做不同的文字切換,比如管理者會看到"管理中心",而一般使用者登入後看到的是"會員中心"

今天先做這樣,我們了解到了 routecontroller, Vue Component, Provider 之間的一些關聯,將來隨著更多的功能加入,會需要了解的也更多。


上一篇
Day04 使用內建的會員系統Breeze
下一篇
Day06 不同角色登入導向
系列文
LV的全端開發體驗30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言