# 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/`

## 用全域方法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**則是每個頁面都是不一樣的內容

類似物件導向中繼承的概念
有一個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

##### 前端插入程式碼

##### `.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
```