---
# System prepended metadata

title: Laravel 8
tags: [Laravel]

---

# Laravel 8
[TOC]
# Laravel 環境安裝
>[color=#00FF00] Laravel環境安裝：https://dometi.com.tw/blog/laravel-beginner-02/

安裝指令
```
composer create-project laravel/laravel --prefer-dist
```

# Laravel 專案架構
>[color=#00FF00] Laravel專案架構：https://dometi.com.tw/blog/laravel-beginner-03/
# Route
>[color=#00FF00]Laravel Routing 路由控制： https://dometi.com.tw/blog/laravel-beginner-05/
## Route寫法
從 `web.php` 的內容可以看到
```javascript
Route::get('/', function () {
    return view('welcome');
})
```
這一串的意思就是，當從client端得到<font color="#f00">`get`</font>要求<font color="#f00">`/`</font>(網站根目錄)，route會呼叫一個function，內容是回傳<font color="#f00">`welcome`</font>這個view


Route方法的結構式:
```javascript
Route::{HTTP verb}($url, $callback);
```
Laravel Routing支援的HTTP verb包含了6種:
* GET – 取得資源
* POST – 新增一筆資源
* PUT – 更新一筆資源
* Patch – 更新一筆資源的部分內容
* Delete – 刪除一筆資源
* Options – 取得Server支援的Request Types有哪些

```javascript
Route::get($url, $callback);
Route::post($url, $callback);
Route::put($url, $callback);
Route::patch($url, $callback);
Route::delete($url, $callback);
Route::options($url, $callback);
```

<font color="#f00">`$url`</font>代表接收到的網址，像根目錄就是<font color="#f00">`/`</font>，而登入可能是<font color="#f00">`/login`</font>

<font color="#f00">`$callback`</font>代表處理這個要求的方法

如果是單純回傳view，可以像`web.php`的寫法一樣
```javascript
Route::get('/', function ()
{
    return view('welcome');
});
```

也可以寫成
```javascript
Route::view('/', 'welcome');
```

如果要進行比較複雜的處理，我們通常會轉給Controller進行處理
```javascript
Route::get('user/profile', 'UserController@showProfile');
```
這一串表示當接到 <font color="#f00">`user/profile`</font> 這個網址要求， route 會去呼叫 <font color="#f00">`UserController`</font> 裡面的 <font color="#f00">`showProfile`</font> 這個function

## Route傳遞參數

**必需參數傳遞方式:**
```javascript
Route::get('post/{id}', 'PostController@show');
```
從Client傳來的<font color="#f00">`{id}`</font>就會傳給<font color="#f00">`PostController`</font>的<font color="#f00">`Show()`</font>來中進行處理，最後回傳資源給Client

**可選參數傳遞方式:**
```javascript
Route::get('users/{name?}', function ($name = 'Chase')
{
    return 'Hello, I am ' .$name;
});
```

<font color="#f00">`{name?}`</font> 代表的就是可選擇的參數，相較於前一個參數傳遞，差別在 <font color="#f00">`{id}`</font> 一定要有參數傳入，而 <font color="#f00">`{name?}`</font>不用，可以自己設定沒有傳入參數時的預設值

所以第一種為必需參數(Required Parameters)，第二種為可選參數(Optional Parameters)

## Route的命名


假設今天有這樣的Route
```javascript
Route::get('post', 'PostController@index');
Route::post('post', 'PostController@create');
```
你可能會使用 <font color="#f00">`url('/login')`</font> 來取得網址，但一個是<font color="#f00">`get`</font>，一個是<font color="#f00">`post`</font>有時可能會搞混。

此時如果可以幫Route命名一下

```javascript
Route::get('post', 'PostController@index')->name('post.index');
Route::post('post', 'PostController@login')->name('post.login');
```

如此一來，只需要使用 <font color="#f00">`route('post.index')`</font> / <font color="#f00">`route('post.login)'`</font> 就可以取得它們的網址了

## Route的群組
### Prefixes前綴群組
Prefixes最主要就是去群組同樣路徑下的網址，可以少打一些路徑名稱
```javascript
Route::prefix('admin')->group(function ()
{
    Route::get('users', function ()
    {
        //所以網址要是/admin/users才會進來這裡
    });
});
```
### Middleware
Middleware的概念是把一群Route群組起來，經過驗證才可以進入存取
```javascript
Route::middleware(['member'])->group(function () {
    Route::get('member_center', function () {
        // 經過member middleware驗證後才能進入
    });
});
```
Middleware是一個過濾機制，讓Client在存取某些資源時必須先經過驗證，否則會被導向其他地方

#### Middleware['auth'] 判斷使用者是否登入，若未登入則重新導向

route
```javascript
Route::middleware(['auth'])->group(function () {
    Route::resource('main', 'App\Http\Controllers\UserInfoController');
});

Route::get('login', array('uses' => 'App\Http\Controllers\HomeController@showLogin'))->name('login.login');
```
app/Http/Middleware/Authenticate.php
```javascript
namespace App\Http\Middleware;

use Illuminate\Auth\Middleware\Authenticate as Middleware;

class Authenticate extends Middleware
{
    /**
     * Get the path the user should be redirected to when they are not authenticated.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return string|null
     */
    protected function redirectTo($request)
    {
        if (! $request->expectsJson()) {
            return route('login.login');//設定導向的路由名稱
        }
    }
}
```

# Middleware 中介層
```
> php artisan make:middleware NoAuthority
```
NoAuthority.php
```javascript
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Gate;

class NoAuthority 
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if(Gate::allows('admin')) return $next($request);
        abort(404);
    }
}
```


到app/Http/Kernel.php註冊Middleware
```javascript
...
    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
        'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
        'no.auth' => \App\Http\Middleware\NoAuthority::class,//this
    ];
```
route
```javascript
    Route::middleware(['no.auth'])->group(function () 
    {
        Route::view('test', 'test');//先經過middleware判斷在執行此行
    });
```






# Views
>[color=#00FF00] Views, Blade Templates：https://dometi.com.tw/blog/laravel-beginner-06/

## view在Laravel的位置
Views路徑為`/resources/views/`

![](https://i.imgur.com/aIuPu6b.png)

## 用全域方法view()呼叫view
```javascript
view('welcome');
```
這個就是使用view的方式

**`view($view_name)`** 是一個全域的方法，你可以在任何地方呼叫它，它會傳回在<font color="#f00">`/views`</font>下的view

**`$view_name`** 是你想要使用的view的名字，像是如果你想要使用`welcome.blade.php`，它的名字就會是'welcome'

如果在<font color="#f00">`/views`</font>底下建立一個資料夾，命名為frontend，並且將`welcome.balde.php`放入frontend之中，這時，如果只是直接重新整理頁面，就會找不到該view。

因此當view的路徑變化時， $view_name 也必須變化：
```javascript
Route::get('/', function () {
    return view('frontend.welcome');
    //return view('frontend/welcome'); 同上方法
});
```

## view()配合參數傳遞

/route/web.php：

```javascript
Route::get('/', function () {
    return view('frontend.welcome', ['name' => '大帥哥']);
});
```

/resources/views/**welcome.blade.php**：
```javascript
<div class="title m-b-md">
    很高興見到你，{{ $name }}
</div>
```

:::info
語法：
```javascript
view($view_name, $data)
```
要特別注意的是， <font color="#f00">`$data`</font> 必須是一個鍵值對應(key/value pairs)的陣列，一個key對應到一個value，讓你在view中可以用 <font color="#f00">`{{$key}}`</font> 的方式使用，像是範例中的'name'對應到'大帥哥'，然後在view中便可用 <font color="#f00">`{{$name}}`</font> 去印出'大帥哥'
:::

## Blade Template簡介

Blade是Laravel的樣板引擎，具有繼承的概念，讓頁面能夠輕易地拆分成區塊(section)並重複使用，減少寫前端時許多重複的內容。

根據它的頁面，我們可以將它劃分出幾個區塊，**Header**, **Navigation**, **Content**, **Footer**。其中**Header**, **Footer**在每個頁面都是一樣的，**Navigation**會根據在哪個頁面，將那個頁面的文字Highlight，**Content**則是每個頁面都是不一樣的內容

![](https://i.imgur.com/L2VHgJT.jpg)

類似物件導向中繼承的概念

有一個master.blade.php，它先include header, navbar, footer，留下一個content等著被實作(@yield)

而頁面home, about, product, store去繼承master(@extends)，再各自去實作出content的內容

## Blade 語法
### Blade 基本語法
按照上述範例簡單實作架構如下

**master.blade.php：**
```htmlmixed
<!DOCTYPE html>
<html lang="zh-TW">
<head>
    <title>Coffee Shop-@yield('title')</title>
</head>
<body>
    @include('frontend.layouts.header')
    @include('frontend.layouts.navbar')
    @yield('content')
    @include('frontend.layouts.footer')
</body>
</html>
```

**home.blade.php：**
```javascript
@extends('frontend.layouts.master')
@section('title', 'Home')   {{-- 因應不同頁面給予不同title --}}
@section('content')
    {{-- 這邊放Home頁面的內容 --}}
@endsection
```
:::info
<font color="#f00">`@include($name)`</font> – 插入 **`$name`** view

<font color="#f00">`@extends($name)`</font> – 繼承 **`$name`** view

<font color="#f00">`@yield($name)`</font> – 等待被繼承後填入內容

<font color="#f00">`@section($name)`</font> – 將內容填入 <font color="#f00">`@yield($name)`</font> ，繼承的樣板中必須要有對應的yield
:::

### Blade 控制語法

**if判斷**
```javascript
@if (count($records) === 1)
    I have one record!
@elseif (count($records) > 1)
    I have multiple records!
@else
    I don't have any records!
@endif
```

**switch判斷**
```javascript
@switch($i)
    @case(1)
        First case...
        @break
    @case(2)
        Second case...
        @break
    @default
        Default case...
@endswitch
```

**Loop迴圈，for, foreach, while和forelse**
```javascript
@for ($i = 0; $i < 10; $i++)
    The current value is {{ $i }}
@endfor
@foreach ($users as $user)
    <p>This is user {{ $user->id }}</p>
@endforeach
@forelse ($users as $user)
    <li>{{ $user->name }}</li>
@empty
    <p>No users</p>
@endforelse
@while (true)
    <p>I'm looping forever.</p>
@endwhile
```

**continue和break**
```javascript
@foreach ($users as $user)
    @continue($user->type == 1)
    <li>{{ $user->name }}</li>
    @break($user->number == 5)
@endforeach
```

# Blade 實作
>[color=#00FF00] https://dometi.com.tw/blog/laravel-beginner-07/
>https://dometi.com.tw/blog/laravel-beginner-08/

# Database in Laravel
## Migration

若僅要migrate部分migrations，到資料表`migrations`將要不要遷移的migrations的欄位的<font color="#f00">`batch`</font>改成<font color="#f00">`1`</font>(<font color="#f00">`2`</font>為最高遷移條件)

若要對表做其他動作(如新增欄位)，則新增一個migration文件
```
> php artisan make:migration insert_users_column 
```
然後再文件裡做想要的處理接著再migrate
```javascript
    public function up()
    {
        Schema::table('users', function($table) {
            $table->string('test2', 20);
        });
    }

    public function down()
    {
        Schema::table('users', function($table) {
            $table->dropColumn('test2');
        });
    }
}
```
接著在migrate
```
> php artisan migrate
```
則<font color="#f00">`batch`</font>為<font color="#f00">`2`</font>的migration文件才會進行migrate，剛剛新增的`insert_users_column`就會執行，而一開始的`create_users_table`因為<font color="#f00">`batch`</font>改成<font color="#f00">`1`</font>了所以不會migrate

## Seeder
在 seeder 類別裡只會預設一個方法：`run`。當執行 `db:seed Artisan` 指令 時就會呼叫此方法。在 `run` 方法中，你可以新增任何想要的數據至你的資料庫中。你可使用 `DB 查詢產生器` 手動新增數據或你也可以使用 `Eloquent` 模型工廠。

```javascript
namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Eloquent;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        Eloquent::unguard();//使model內原本無法更動的欄位可更動

        $this->call(UserTableSeeder::class);
    }
}

```

```javascript
namespace Database\Seeders;

use Illuminate\Foundation\Auth\User;
use Illuminate\Database\Seeder;
use DB;
use Hash;

class UserTableSeeder  extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        DB::table('users')->delete();
        User::create(array(
            'name'     => 'Test Name',
            'username' => 'test',
            'email'    => 'chris@scotch.io',
            'password' => Hash::make('1234'),
        ));
    }
}
```




# 範例 - Laravel 8 REST API CRUD，搭配Bootstrap 4和MySQL
>[color=#00FF00]  **CRUD範例1：** https://www.techiediaries.com/laravel-8-rest-api-crud-mysql/

>[color=#00FF00]  **範例：** https://itsolutionstuff.com/post/laravel-8-crud-application-tutorial-for-beginnersexample.html


1.打開`.env`文件並更新以訪問您的MySQL數據庫
```
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=your database
DB_USERNAME=your username
DB_PASSWORD=your password
```

2.在cmd中運行migrate命令來創建數據庫和Laravel所需的SQL表：
```
php artisan migrate
```
## 創建Model
3.創建Laravel model。在cmd運行以下命令：
```
php artisan make:model Contact --migration
```

這將在Laravel 8的`app/Models`目錄中創建model - `Contact.php`，並在資料庫目錄中創建一個migrations。

:::success
成功後輸出
```
Model created successfully.
Created Migration: 2020_09_20_193840_create_contacts_table
```
:::


4.打開位於database/migrations下的`database/migrations/xxxxxx_create_contacts_table`並修改

```laravel
<?php

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

class CreateContactsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('contacts', function (Blueprint $table) {
            $table->increments('id');
            $table->timestamps();
            $table->string('first_name');
            $table->string('last_name');
            $table->string('email');
            $table->string('job_title');
            $table->string('city');   
            $table->string('country');            
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('contacts');
    }
}
```
在contacts表裡添加了first_name,last_name,email,job_title,city,country表格

5.使用以下命令在資料庫中創建表：
```
php artisan migrate
```

6.接著打開`app/Models/Contact.php`並修改。該Model將用於和資料庫表進行交互
```laravel
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Contact extends Model
{
    protected $fillable = [
        'first_name',
        'last_name',
        'email',
        'city',
        'country',
        'job_title'       
    ];
}
```
## 創建controller和route

7.創建Model並migrate我們的資料庫之後。接著創建controller和route來運行Contact model。在cmd運行以下命令：
```
php artisan make:controller ContactController --resource
```

8.打開`app/Http/Controllers/ContactController.php`。這是初始內容：
```laravel
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ContactController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        //
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        //
    }
}
```

ContactController該類擴展Controller了Laravel提供的類，並定義了一堆方法，這些方法將用於對Contact模型執行CRUD操作。

9.添加路由。打開`routes/web.php`文件並修改：
```laravel
<?php
Route::get('/', function () {
    return view('welcome');
});

Route::resource('contacts', 'App\Http\Controllers\ContactController');
```
:::info
:bulb:兩方法等價
```laravel
Route::resource('contacts', 'App\Http\Controllers\ContactController');
Route::resource('contacts', ContactController::class);
```
:::

<font color="#f00">*</font>使用Route的resource()靜態方法，可以創建多個Route以公開使用Route的resource上的多個操作。
<font color="#f00">*</font>這些Route映射到ContactController下一部分將需要實現的各種方法：

GET /contacts，映射到`index()`方法，
GET /contacts/create，映射到`create()`方法，
POST /contacts，映射到`store()`方法，
GET /contacts/{contact}，映射到`show()`方法，
GET /contacts/{contact}/edit，映射到`edit()`方法，
PUT / PATCH /contacts/{contact}，映射到`update()`方法，
DELETE /contacts/{contact}，映射到`destroy()`方法。

:::info
:bulb: 
`index()`：列表、清單
`create()`：指新增時的頁面，所以是GET
`store()`：新增一筆資料來進行"儲存"的這個動作
`show()`：與index不同在於`index()`是多筆而`show()`是單筆
`edit()`：編輯頁面
`update()`：`PUT`全部更新，`PATCH`部分更新
`destroy()`：刪除
:::

# validate驗證
>[color=#00FF00] 參考 https://hackmd.io/@8irD0FCGSQqckvMnLpAmzw/HJ1LqggUQ?type=view
```javascript
public function store(Request $request)
{
    //驗證規則
    $rules = [
        'country_name' => 'required|max:255',
        'symptoms' => 'required',
        'cases' => 'required|numeric',
    ];
    //驗證失敗返回訊息
    $messages = [
        'country_name.required' => '請輸入country_name',
        'symptoms.required' => '請輸入symptoms',
        'cases.required' => '請輸入cases',
        'cases.numeric' => 'cases必須是數字',
    ];
    //將填入的資料驗證
    $validatedData = $request->validate($rules, $messages);
    //在Corona model裡建立填入的新資料
    $show = Corona::create($validatedData);
    //重新導向並帶入訊息
    return redirect('/coronas')->with('success', 'Corona Case is successfully saved');
}
```

# Gate 使用者角色、權限分級
>[color=#00FF00] 參考 https://officeguide.cc/larave-6-implement-user-roles-and-permissions-using-gates/

使用者角色
/app/Models/User.php
```javascript
    ...
    public function isAdmin(){
        if($this->authority == 1) return true;
    }

    public function isUser(){
        if($this->authority == 0) return true;
    }
```

建立 Gate 權限規則
/app/Providers/AuthServiceProvider.php
```javascript
    public function boot()
    {
        $this->registerPolicies();
        
        // 管理者
        Gate::define('admin', function ($user) {
            if($user->isAdmin()) return true;
        });

        // 使用者
        Gate::define('user', function ($user) {
            if($user->isUser()) return true;
        });

    }
```
```javascript=
//another example
    public function someAction()
    {
        if (Gate::allows('admin')) {
            return '系統管理者。';
        }

        if (Gate::denies('admin')) {
            return '非系統管理者！';
        }
    }
```
```javascript=
//another example
    // 只有系統管理者可以執行
    public function adminAction()
    {
        $this->authorize('admin');

        // ...
    }
```
Controller 運用 Gate 權限設定
在 Controller 中則可使用 `Gate::allows` 或 `Gate::denies` 判斷使用者權限：
```javascript
...
    if (Gate::allows('admin')) return view('test');
    if (Gate::allows('user')) return redirect('dashboard');
...

```
## Blade 運用 Gate 權限設定
在 Blade 樣板中可以運用 `@can`、`@cannot` 或 `@canany` 來判斷使用者的權限
```javascript
@can('admin')
    <!-- 管理者 -->
@elsecan('user')
    <!-- 使用者 -->
@else
    <!-- 其他 -->
@endcan
```
## Middleware 運用 Gate 權限設定
```javascript
// 只有系統管理者可以執行
Route::get('/someAction', 'MyController@someAction') -> middleware('can:admin');
```

# Laravel Eloquent ORM
>[color=#00FF00] https://laravel.tw/docs/5.0/eloquent
> https://ithelp.ithome.com.tw/articles/10209583
## Model::新增

### Model::Create方法
```javascript
//laravel official-
// 在資料庫中建立一個新的使用者...
$user = User::create(['name' => 'John']);

// 以屬性找使用者，若沒有則新增並取得新的實例...
$user = User::firstOrCreate(['name' => 'John']);

// 以屬性找使用者，若沒有則建立新的實例...
$user = User::firstOrNew(['name' => 'John']);
```


## Model::取出資料

### Model::all() - 取出所有資料
```javascript
$users = User::all();
```
### Model::find() - 取出特定資料
```javascript
//根據主鍵取出一筆資料
$user = User::find(1);

var_dump($user->name);
```
### Model::findOrFail() - 取出一條資料或拋出異常
```javascript
public function edit($id)
{
    //根據主鍵取出一條資料或拋出異常
    $coronacase = Corona::findOrFail($id);
    return view('edit', compact('coronacase'));
}

//laravel official-
$model = User::findOrFail(1);

$model = User::where('votes', '>', 100)->firstOrFail();

```

## Model::更新

### Model::update()
```javascript
public function update(Request $request, $id)
{
    $validatedData = $request->validate([
        'country_name' => 'required|max:255',
        'symptoms' => 'required',
        'cases' => 'required|numeric',
    ]);
    Corona::whereId($id)->update($validatedData);
    return redirect('/coronas')->with('success', 'Corona Case Data is successfully updated');
}
```

## Model::刪除

### Model::delete()
```javascript
public function destroy($id)
{
    $coronacase = Corona::findOrFail($id);
    $coronacase->delete();
    return redirect('/coronas')->with('success', 'Corona Case Data is successfully deleted');
}

//laravel offical-
//刪除模型
//要刪除模型，只要使用實例呼叫 delete 方法：

$user = User::find(1);

$user->delete();
//依主鍵值刪除模型
User::destroy(1);

User::destroy([1, 2, 3]);

User::destroy(1, 2, 3);
//當然，您也可以結合查詢語句批次刪除模型：

$affectedRows = User::where('votes', '>', 100)->delete();
```

## Model 批量賦值（Mass Assignment）
如果盲目的存入使用者輸入，使用者可以隨意的修改任何以及所有模型的屬性。基於這個理由，所有的 Eloquent 模型預設會防止批量賦值。
### 定義模型 Fillable 屬性
`fillable` 屬性指定了可以被批量賦值的欄位。可以設定在類別裡或是建立實例後設定。
```javascript
//只有三個屬性允許被批量賦值。
class User extends Model {

    protected $fillable = ['first_name', 'last_name', 'email'];

}
```
### 定義模型 Guarded 屬性
`guarded` 與 `fillable` 相反，是作為「黑名單」而不是「白名單」
```javascript
//這兩個屬性無法被更動
class User extends Model {

    protected $guarded = ['id', 'password'];

}
//阻擋所有屬性被批量賦值
protected $guarded = ['*'];
```

# JetStream

## profile圖片路徑

.env
```
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:6Z0KjdxghIp7Ck4Ni4mDhhpkiQhsbv5N1hIGSau5QZQ=
APP_DEBUG=true
APP_URL=http://laravel.local << 需和網頁URL一致

...
```
/config/filesystems
```javascript
    ...
    
    'disks' => [

        'local' => [
            'driver' => 'local',
            'root' => storage_path('app'),
        ],

        'public' => [
            'driver' => 'local',
            'root' => storage_path('app/public'),
            'url' => env('APP_URL').'/storage',//確定是否為此路徑
            'visibility' => 'public',
        ],

        's3' => [
            'driver' => 's3',
            'key' => env('AWS_ACCESS_KEY_ID'),
            'secret' => env('AWS_SECRET_ACCESS_KEY'),
            'region' => env('AWS_DEFAULT_REGION'),
            'bucket' => env('AWS_BUCKET'),
            'url' => env('AWS_URL'),
            'endpoint' => env('AWS_ENDPOINT'),
        ],

    ],
    
    ...
```
接著下指令在建立storage在/public快捷
```
> php artisan storage:link
```

# TimeZone
>[color=#00FF00]  參考 https://blog.xuite.net/dizzy03/murmur/585392198-%5B%E8%BD%89%5D%5BLaravel%5D+Laravel+5.4+%E8%A8%AD%E5%AE%9A%E6%99%82%E5%8D%80
/config/app.php
```javascript
...
    'timezone' => 'Asia/Taipei',
...
```
設定完之後refresh可能還沒生效

要執行
```
php artisan cache:clear

php artisan view:clear

php artisan config:cache
```

# API
>[color=#00FF00] 1.https://hosomikai317.blogspot.com/2020/02/laravel-swagger-api.html
>[color=#00FF00] 2. https://segmentfault.com/a/1190000038372088

## controller
```laravel
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ProjectsController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
       /**
        * @OA\Get(
        *     path="/test",
        *     @OA\Response(response="200", description="Display a listing of projects.")
        * )
        */
    }
                        .
                        .
                        .
}

```

# Laravel WebSocket with Pusher 廣播
>[color=#00FF00] pusher官網： https://pusher.com/?utm_source=google_ads&utm_medium=homepage&utm_campaign=comp_brand_search&gclid=Cj0KCQjww4OMBhCUARIsAILndv43rTs6VmsB7I32QfqI7WJTxrLfI5fh6CSVkXseVJEC1jGVE-_Ky4QaArodEALw_wcB

>[color=green]https://ithelp.ithome.com.tw/articles/10231475
##### 註冊並建立channel
![](https://i.imgur.com/KvRcp3y.png)

##### 前端插入程式碼
![](https://i.imgur.com/unHfbX0.png)

##### `.env`修改

```laravel
BROADCAST_DRIVER=pusher
.
.
.
PUSHER_APP_ID=XXXXXXX
PUSHER_APP_KEY=XXXXXXXXXXXXXXXXXXXX
PUSHER_APP_SECRET=XXXXXXXXXXXXXXXXXXXX
PUSHER_APP_CLUSTER=ap3
```

##### `config/broadcasting.php`修改
```laravel
'options' => [
  'cluster' => 'ap3',
  'useTLS' => true
],
```
##### 安裝pusher套件
```
$ composer require pusher/pusher-php-server
```
##### 新增事件`App/Events/MyEvent`
```laravel
<?php

namespace App\Events;

use Illuminate\Queue\SerializesModels;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class MyEvent implements ShouldBroadcast
{
  use Dispatchable, InteractsWithSockets, SerializesModels;

  public $message;

  public function __construct($message)
  {
      $this->message = $message;
  }

  public function broadcastOn()
  {
      return ['my-channel'];
  }

  public function broadcastAs()
  {
      return 'my-event';
  }
}
```
##### 觸發事件

```laravel
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Events\MyEvent;


class PushController extends Controller
{
    public function push(Request $request)
    {
        $message = $request->get('message');
        
        // 分發工作給事件(同queue運作原理)
            event(new MyEvent($message)); 
        
        $msg = "訊息'$message'已發送";
        return redirect('pusher_test_push')->with('msg', $msg);
    }

}

```
:::info
:bulb:
需執行
```
php artisan queue:listen
```
來讓廣播訊息推播出去
:::



# 錯誤解決
## Illuminate\Http\UploadedFile Error 1 
是指上傳的文件大小超出了 PHP.ini 文件中 upload_max_filesize 的限制，這是由於 PHP 服務器設置的限制引起的。
解決此問題，您需要增加 PHP.ini 文件中的 upload_max_filesize 限制。您可以按照以下步驟執行：

1. 打開 PHP.ini 文件
2. 找到 upload_max_filesize 選項，然後將其值更改為更高的限制
3. 保存 PHP.ini 文件，並重新啟動您的 Web 服務器。
## No Application Encryption Key Has Been Specified
APP_KEY 不見，若為測試環境可用指令產生新加密 key
```console
$ php artisan key:generate
```
# NoSQL ORM
- 查詢
```php
DB::connection('mongodb')->collection('collection_name')->get();
```
- 新增
```php
// return true
DB::connection('mongodb')->collection('collection_name')->insert(['key' => 'value']);
```
- 修改
```php
// where 用法同 ORM
// return 修改筆數
DB::connection('collection_name')->collection('users')->where('key', '=', 'value')->update(['key' => 'value']);
```
- 刪除
```php
// return 刪除筆數
DB::connection('mongodb')->collection('collection_name')->where(["key" => "value"])->delete();
```

# Component
>[color=green] https://ithelp.ithome.com.tw/articles/10288267

產生指令
```console
$ php artisan make:component component_name
```
在網頁畫面內呼叫這個元件，可以用 **`x-`** 開頭的方式，加上元件的命名
```php
<x-component_name>
```
如果元件的名稱較長，命名就要以 **`-`** 進行區隔
```php
<x-user-profile>
```
如果元件的位置在 `views/components/` 的資料夾內，那就要以 . 的方式命名

比方說，如果元件位於 `views/components/inputs/alert.blade.php`
```php
<x-inputs.alert>
```
放置變數
1. **`View/Components/component_name.php`** 建立變數
```php
class component_name extends Component
{
    /**
     * Create a new component instance.
     *
     * @return void
     */
    public $type;
    public $message;
    public function __construct($type, $message)
    {
        //
        $this->type = $type;
        $this->message = $message;
    }
.
.
.
```
2. **`views/components/component_name.blade.php`** 設定 blade 變數位置
```php
<div class="alert alert-{{ $type }}">
    {{ $message }}
</div>
```

3. 使用
```php
<!-- 直接帶入 -->
<x-component_name :type="warning" :message="測試" />

<!-- 後端回傳變數 -->
<x-component_name :type="$type" :message="$message" />
```

# Command
>[color=green]https://inbound.technology/laravel-command-artisan-%E6%98%AF%E4%BB%80%E9%BA%BC%E6%9C%83%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E5%AE%83/
1. 建立 command
```console
$ php artisan make:command command_name
```
<br>

2. 命名
```php
protected $signature = 'print:number {num}';
```
第二段的 `protected $description = 'Command description';` 則是功能說明，.會出現在 `php artisan list` 之中。
<br>
3. 功能

第三段的 `public function handle()` 為主程式
EX:
```php
public function handle()
{
    $num = $this->argument('num');
    while(--$num)
        print("$num  ");
    return 0;
}
```
4. 執行
```console
$ php artisan try01:number 5
5  4  3  2  1 
```