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