Laravel 8 建置筆記

by 3 月 12, 2021開發筆記0 comments

目錄

Inertia 有夠神奇,太怪了直接棄用

vscode prettier 排版:

─ npm install --save-dev prettier @prettier/plugin-php

laravel 8 前端測試

我這兩周以 laravel 8 測試了:

  • jetstream + inertia(vue3) + tailwindcss
  • jetstream + inertia(vue3) + bootstrap
  • jetstream + livewire(php) + tailwindcss
  • jetstream + livewire(php) + bootstrap
  • breeze
  • auth ui + vue2 + bootstrap

在 vue template 的 form 裡面會有 csrf 的問題

<input type="hidden" name="_token" :value="csrf" />
data() {
    return {
      csrf: document
        .querySelector('meta[name="csrf-token"]').getAttribute("content"),
       },
   }

後端驗證回傳 vue

https://www.codecheef.org/article/dynamic-form-validation-in-laravel-using-vue-js

vue

<template>
  <div class="container">
    <div class="alert alert-success" role="alert" v-if="success"> 儲存成功 </div>

    <h1 class="text-uppercase">example</h1>
    <form>
      <div class="form-group">
        <label>INPUT</label>
        <input
          type="text"
          :class="['form-control', errors.input01 ?'is-invalid':'']"
          v-model="input01"
        />
        <div class="invalid-feedback" v-if="errors.input01">
          {{errors.input01[0] }}
        </div>
      </div>

      <div class="form-group form-check">
        <input type="checkbox" class="form-check-input" id="exampleCheck1" />
        <label class="form-check-label" for="exampleCheck1">Check me out</label>
      </div>
      <button type="submit" class="btn btn-primary" @click.prevent="submit()">
        Submit
      </button>
    </form>
  </div>
</template>
<script>
// var fd = new FormData();
const methods = {submit: function () {
    this.success = "";
    this.errors = [];
    // fd.append("input01", this.input01);
    let fd = {input01: this.input01,};
    axios
      .post("example", fd)
      .then((res) => {
        this.success = true;
        console.log(res);
      }).catch((err) => {console.log(err.response);
        this.errors = err.response.data.errors;
      });},
};
export default {data() {
    return {
      input01: "",
      errors: [],
      success: "",
    };
  },
  methods,
};
</script>

controller

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ExampleController extends Controller
{
  //
  public function post(Request $request)
  {
    $validator = $request->validate(
      ["input01" => "required",],
      ["input01.required" => "這是必填欄位",]
    );
    return $request;
  }
}

sanctum

參考資料

https://zhuanlan.zhihu.com/p/130226534

https://blog.codecourse.com/setting-up-laravel-sanctum-airlock-for-spa-authentication-with-vue/

Vue 在 laravel 使用 components 的 @ 路徑問題

一般在用 vue cli 時可以用 @代表一個 root 路徑,但在 laravel 要使用必須在 webpack.mix.js 作以下調整

const mix = require("laravel-mix");

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel application. By default, we are compiling the Sass
 | file for the application as well as bundling up all the JS files.
 |
 */

mix.webpackConfig({
  resolve: {extensions: [".js", ".vue", ".json"],
    alias: {
      vue$: "vue/dist/vue.esm.js",
      "@": __dirname + "/resources/js",
    },
  },
});

mix
  .js("resources/js/app.js", "public/js")
  .vue().sass("resources/sass/app.scss", "public/css");

資料型態為 json 時的處理方式

由於前端送物件型態時,一般來說要用 JSON.stringfy(物件) 的方式將資料改成 string,然後主機端用 longText 的欄位來存,未來要用時前端得用 JSON.parse(物件) 的方式來將文字轉成物件,這樣很麻煩,所以 laravel 有一套機制來處理

刺用 model 的 cast 功能將資料型別轉換:

protected $casts = ["payment_info" => "array",];

這樣前端送值時 payment_info 欄位的資料會自動存成物件

取出關聯時若沒有關聯則回傳空值的方法

$order = $user->orders ?? [];

postman 419 報錯

用 web.php 路由 post 物件會 419

先在 web.php 寫一隻 getcsrf 路由
在 controller 中

 public function GetCsrf()
  {return csrf_token();
  }

將拿到的 token 在 postman 的header 中增加 X-CSRF-TOKEN
並填入該 token 即可

vuetify pagination

laravel

public function GetProductsPaginate(Request $request)
  {return Product::with(["image"])->paginate(10);
  }

//Here is what works for me with Laravel 5.5 and Vuetify 1.3:

//HTML

<v-pagination
    v-model="pagination.current"
    :length="pagination.total"
    @input="onPageChange"
></v-pagination>
JS

export default {data() {
        return {
            users: null,
            pagination: {
                current: 1,
                total: 0
            }
        }
    },
    methods: {getUsers() {window.axios.get('/api/users?page=' + this.pagination.current)
                .then(response => {
                    this.users = response.data.data;
                    this.pagination.current = response.data.current_page;
                    this.pagination.total = response.data.last_page;
                });},
        onPageChange() {this.getUsers();
        }
    },
    mounted() {this.getUsers();
    }
}
Laravel

public function users()
{$users = User::paginate(10);

    return response($users, 200);
}
//When your component is mounted, getUsers()will get called. pagination.current defaults to 1 so the first page will load. The response will set pagination.total. Vuetify handles binding the page buttons to pagination.current so that when you click one, pagination.current gets set to the page number and then @input triggers getUsers() which uses pagination.current to get the page you selected.