# Laravel

# Laravel 建立專案

先安裝composer ，在切換到放置專案的目錄<textarea style="display: none;">composer global require laravel/installer laravel new example-app cd example-app php artisan serve</textarea>

```shell
composer global require laravel/installer

laravel new example-app

cd example-app

php artisan serve
```

修改參數

```PHP
//config/app.php

'timezone' => 'Asia/Taipei',
'locale' => 'zh_TW',
'faker_locale' => 'zh_TW',
```

加上Ｖue

[laravel8 + vue3.0 + element-plus 搭建 | IT人 (iter01.com)](https://iter01.com/590621.html)

[Laravel SPA with Vue 3, Auth (Sanctum), CRUD Example - Shouts](https://shouts.dev/laravel-spa-with-vue3-auth-crud-example)

# Laravel 常見問題: Specified key was too long

<header class="entry-header" id="bkmrk-laravel-%E5%B8%B8%E8%A6%8B%E5%95%8F%E9%A1%8C%3A-specif"><span style="color: #444444;">Laravel 在 5.4 版之後為了支援 emoji , 因此將資料編碼改為 utf8mb4. 由於 utf8mb4 的儲存空間需求膨脹了4倍, 導致預設長度無法正常寫入資料庫.</span></header>這個問題會在 MySQL 5.7.6 以下與 MariaDB 的環境中出現以下錯誤

<div id="bkmrk-%5Bpdoexception%5D-sqlst"><div>```
[PDOException]
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes
```

</div></div>在 Migrate 過程中出現這個問題的解決方法有兩種

<div id="bkmrk-%E6%9B%B4%E6%96%B0%E5%88%B0-mysql-5.7.7-%E4%BB%A5%E4%B8%8A%E7%89%88%E6%9C%AC"><div>1. 更新到 MySQL 5.7.7 以上版本
2. 調整 Laravel 的預設資料長度

</div></div>升級 MySQL 的方法就不細說了, 接下來主要說明調整 Laravel 預設值的方法

首先, 編輯專案目錄下的 `app/Providers/AppServiceProvider.php`

新增一個引用

<div id="bkmrk-use-illuminate%5Csuppo"><div>```
use Illuminate\Support\Facades\Schema;
```

</div></div>接著修改 boot function, 將預設長度定為 191

<div id="bkmrk-public-function-boot"><div>```
public function boot()
{
    Schema::defaultStringLength(191);
}
```

</div></div>重新執行 `php artisan migrate` 就不會有問題了

最後附上完整的 AppServiceProvider.php

<div id="bkmrk-namespace-app%5Cprovid">```
namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Schema::defaultStringLength(191);
    }

    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}
```

</div>

# Laravel 解決在 CentOS 7 下 log 檔無法寫入的問題

在 `config/logging.php`

'permission' =&gt; 0775,

```JSON
'daily' => [
        'driver' => 'daily',
        'path' => storage_path('logs/laravel.log'),
        'level' => 'debug',
        'days' => 7,
        'permission' => 0775,
    ],
```

---

在非 homestead 的主機上執行 laravel 時，有時會出現空白畫面，或是以下的錯誤訊息：

```
The stream or file "/xxxx/yyyy/zzzz/storage/logs/laravel-<日期>.log" could not be opened: failed to open stream: Permission denied
```

這是因為我們使用不同的方式執行 laravel 程式，會讓 log 檔有不同權限設定，和沒有檔案的寫入權限。

內容目錄

<div id="bkmrk-%E8%A7%A3%E6%B3%95%E4%B8%80%EF%BC%9A%E5%B0%87-logs-%E7%9B%AE%E9%8C%84%E5%8F%8A%E6%AA%94%E6%A1%88%E6%AC%8A%E9%99%90%E7%9B%B4%E6%8E%A5"><div></div><nav>- [解法一：將 logS 目錄及檔案權限直接設為 777 (不推薦)](https://kirin.idv.tw/laravel-log-stream-open-failed-in-centos-7/#%E8%A7%A3%E6%B3%95%E4%B8%80%EF%BC%9A%E5%B0%87_logS_%E7%9B%AE%E9%8C%84%E5%8F%8A%E6%AA%94%E6%A1%88%E6%AC%8A%E9%99%90%E7%9B%B4%E6%8E%A5%E8%A8%AD%E7%82%BA_777_(%E4%B8%8D%E6%8E%A8%E8%96%A6) "解法一：將 logS 目錄及檔案權限直接設為 777 (不推薦)")
- [解法二：設計好適當的權限](https://kirin.idv.tw/laravel-log-stream-open-failed-in-centos-7/#%E8%A7%A3%E6%B3%95%E4%BA%8C%EF%BC%9A%E8%A8%AD%E8%A8%88%E5%A5%BD%E9%81%A9%E7%95%B6%E7%9A%84%E6%AC%8A%E9%99%90 "解法二：設計好適當的權限")
    - [步驟一：設定群組權限](https://kirin.idv.tw/laravel-log-stream-open-failed-in-centos-7/#%E6%AD%A5%E9%A9%9F%E4%B8%80%EF%BC%9A%E8%A8%AD%E5%AE%9A%E7%BE%A4%E7%B5%84%E6%AC%8A%E9%99%90 "步驟一：設定群組權限")
    - [步驟二：修改「網頁伺服器」的預設檔案存取權限](https://kirin.idv.tw/laravel-log-stream-open-failed-in-centos-7/#%E6%AD%A5%E9%A9%9F%E4%BA%8C%EF%BC%9A%E4%BF%AE%E6%94%B9%E3%80%8C%E7%B6%B2%E9%A0%81%E4%BC%BA%E6%9C%8D%E5%99%A8%E3%80%8D%E7%9A%84%E9%A0%90%E8%A8%AD%E6%AA%94%E6%A1%88%E5%AD%98%E5%8F%96%E6%AC%8A%E9%99%90 "步驟二：修改「網頁伺服器」的預設檔案存取權限")
    - [步驟三、修改「命令列」的預設檔案存取權限](https://kirin.idv.tw/laravel-log-stream-open-failed-in-centos-7/#%E6%AD%A5%E9%A9%9F%E4%B8%89%E3%80%81%E4%BF%AE%E6%94%B9%E3%80%8C%E5%91%BD%E4%BB%A4%E5%88%97%E3%80%8D%E7%9A%84%E9%A0%90%E8%A8%AD%E6%AA%94%E6%A1%88%E5%AD%98%E5%8F%96%E6%AC%8A%E9%99%90 "步驟三、修改「命令列」的預設檔案存取權限")
    - [步驟四、修改 「cron」 的預設檔案存取權限](https://kirin.idv.tw/laravel-log-stream-open-failed-in-centos-7/#%E6%AD%A5%E9%A9%9F%E5%9B%9B%E3%80%81%E4%BF%AE%E6%94%B9_%E3%80%8Ccron%E3%80%8D_%E7%9A%84%E9%A0%90%E8%A8%AD%E6%AA%94%E6%A1%88%E5%AD%98%E5%8F%96%E6%AC%8A%E9%99%90 "步驟四、修改 「cron」 的預設檔案存取權限")
    - [解法二總結](https://kirin.idv.tw/laravel-log-stream-open-failed-in-centos-7/#%E8%A7%A3%E6%B3%95%E4%BA%8C%E7%B8%BD%E7%B5%90 "解法二總結")
- [參考資料](https://kirin.idv.tw/laravel-log-stream-open-failed-in-centos-7/#%E5%8F%83%E8%80%83%E8%B3%87%E6%96%99 "參考資料")

</nav></div>## <span class="ez-toc-section" id="bkmrk--0"></span>解法一：將 logS 目錄及檔案權限直接設為 777 (不推薦)

<div id="bkmrk-chmod--r-777-storage">```php
chmod <span class="token operator">-</span>R <span class="token number">777</span> storage<span class="token operator">/</span>logs<span class="token operator">/</span>
```

<div><div>PHP</div></div></div>**這方法最快，但是只能治標，不能治本，有再度發生的可能；而且，還有安全性的隱憂**

## <span class="ez-toc-section" id="bkmrk--1"></span>解法二：設計好適當的權限

以 CentOS 為例，在 CentOS 中，我們以 apache 的 virtual host 來執行我們的 laravel 系統，會有三個比較常見的狀況：  
一、透過「網頁伺服器」執行程式  
二、透過「命令列」執行程式  
三、透過 「cron」 執行程式  
各會有不同的檔案權限規則應用在新產生的檔案。我們必須針對這三種方式，來規劃不同的權限規則。

### <span class="ez-toc-section" id="bkmrk--2"></span>步驟一：設定群組權限

由於 網頁伺服器的預設執行帳號是 apache，所以其產生的檔案，owner及group 均是 apache；而命令列或 cron，則會根據登入的使用者帳號來設定，為了要讓不同方式產生的檔案，能透過「群組權限」的設定值來存取程式，我們必需做一些設定，假設我們 virtual host 的網頁檔案是以 john 這個帳號來登入的

<div id="bkmrk-%23-%E6%8A%8A-john-%E5%8A%A0%E5%85%A5-apache-%E7%BE%A4">```bash
<span class="token comment"># 把 john 加入 apache 群組</span>
<span class="token function">usermod</span> -a -G apeche john
<span class="token comment"># 也把 apache 加入 john 群組</span>
<span class="token function">usermod</span> -a -G john apache
```

<div><div>Bash</div></div></div>**更改群組後，shell 要重新登入；部分服務需重新開機才能套用群組權限設定**

如果對於 Linux 的檔案權限不太熟悉，可以看一下[鳥哥的文章 - Linux 檔案與目錄管理](http://linux.vbird.org/linux_basic/0220filemanager.php#umask "鳥哥的文章 - Linux 檔案與目錄管理")。

### <span class="ez-toc-section" id="bkmrk--3"></span>步驟二：修改「網頁伺服器」的預設檔案存取權限

apache server 預設的執行帳號是 apache，產生的檔案權限為 644，範例如下：

```
-rw-r--r-- 1 apache apache    153438 12月 24 20:49 laravel-2019-12-24.log

```

我們必須設定 apache 的 umask 設定，讓其產生的檔案權限為 664，這樣一來，apache 群組才具有寫入的權限。

**設定檔 umask.conf 內容**

```
[Service]
UMask=0002
```

指令如下：

<div id="bkmrk-mkdir-%2Fetc%2Fsystemd%2Fs">```bash
<span class="token function">mkdir</span> /etc/systemd/system/httpd.service.d
<span class="token function">vi</span> /etc/systemd/system/httpd.service.d/umask.conf

systemctl daemon-reload
systemctl restart httpd.service
```

<div><div>Bash</div></div></div>### <span class="ez-toc-section" id="bkmrk--4"></span>步驟三、修改「命令列」的預設檔案存取權限

有時我們會透過 php artisan 來執行程式，產生的檔案, 其使用者和群組就是登入的帳號，而權限會根據 umask 來決定其權限。

<div id="bkmrk-%23-%E5%9C%A8-shell-%E4%B8%AD%EF%BC%8C%E7%9B%B4%E6%8E%A5%E8%BC%B8%E5%85%A5-uma">```bash
<span class="token comment"># 在 shell 中，直接輸入 umask 可以查看目前設定</span>
<span class="token function">umask</span>

<span class="token comment"># 修改 umask 為 0002</span>
<span class="token function">umask</span> 0002

<span class="token comment"># 將 umask 0002 的設定加入登入設定檔</span>
<span class="token function">vi</span> ~/.bashrc

```

<div><div>Bash</div></div></div>### <span class="ez-toc-section" id="bkmrk--5"></span>步驟四、修改 「cron」 的預設檔案存取權限

當透過 cron 來進行工作排程時，其所產生的檔案，owner 和 group 是登入帳號，預設的 umask 是，0022，我們可以透過修改設定檔來改變：

<div id="bkmrk-%23-%E4%BF%AE%E6%94%B9%E8%A8%AD%E5%AE%9A%E6%AA%94%EF%BC%8C%E5%9C%A8%5Bservice%5D-%E6%AE%B5">```bash
<span class="token comment"># 修改設定檔，在[Service] 段中，加入 UMask=0002</span>
<span class="token function">vi</span> /usr/lib/systemd/system/crond.service

systemctl daemon-reload
systemctl restart crond.service
```

<div><div>Bash</div></div></div>重新啟動 cron 服務後，其所產生的檔案權限就會變為 664

### <span class="ez-toc-section" id="bkmrk--6"></span>解法二總結

解法二的處理方式是要達到 2 個目標  
1、三種執行方式所產生的 log 檔案，不管 owner 是 apache 或是 john，其權限都是 664  
2、apache 和 john 這兩個帳號，都加入對方的群組中

來源：[https://kirin.idv.tw/laravel-log-stream-open-failed-in-centos-7/](https://kirin.idv.tw/laravel-log-stream-open-failed-in-centos-7/)

# Laravel jwt登入驗證

[Laravel API 系列教程（二）: 结合 Laravel 5.5 和 Vue SPA 基于 jwt-auth 实现 API 认证 | 构建 API 接口：原生开发 | Laravel 入门到精通教程 (laravelacademy.org)](https://laravelacademy.org/post/9178)

```PHP
 #config/app.php
   'providers' => [
	 #LaravelServiceProvider::class 要改成這個
        Tymon\JWTAuth\Providers\LaravelServiceProvider::class,
    ],

```

# Laravel migration 可使用的欄位類型

#### 可使用的欄位類型

資料庫 Schema 生成器包含表格常用的各種欄位類型，如下所列：

<table class="table table-striped" id="bkmrk-%E7%A8%8B%E5%BC%8F%E7%A2%BC-%E8%AA%AA%E6%98%8E-%24table-%3Eid%28%29%3B"><thead><tr><th>程式碼</th><th>說明</th></tr></thead><tbody><tr><td>$table-&gt;id();</td><td>$table-&gt;bigIncrements('id') 的別名</td></tr><tr><td>$table-&gt;foreignId('user\_id');</td><td>$table-&gt;unsignedBigInteger('user\_id') 的別名</td></tr><tr><td>$table-&gt;bigIncrements('id');</td><td>遞增 ID（主鍵），相當於「UNSIGNED BIG INTEGER」</td></tr><tr><td>$table-&gt;bigInteger('votes');</td><td>相當於 BIGINT</td></tr><tr><td>$table-&gt;binary('data');</td><td>相當於 BLOB</td></tr><tr><td>$table-&gt;boolean('confirmed');</td><td>相當於 BOOLEAN</td></tr><tr><td>$table-&gt;char('name', 100);</td><td>相當於帶有長度的 CHAR</td></tr><tr><td>$table-&gt;date('created\_at');</td><td>相當於 DATE</td></tr><tr><td>$table-&gt;dateTime('created\_at', 0);</td><td>相當於 DATETIME ，可以指定位數</td></tr><tr><td>$table-&gt;dateTimeTz('created\_at', 0);</td><td>相當於 DATETIME (帶時區) ，可以指定位數</td></tr><tr><td>$table-&gt;decimal('amount', 8, 2);</td><td>相當於 DECIMAL，可以指定總位數和小數位數</td></tr><tr><td>$table-&gt;double('amount', 8, 2);</td><td>相當於 DOUBLE，可以指定總位數和小數位數</td></tr><tr><td>$table-&gt;enum('level', \['easy', 'hard'\]);</td><td>相當於 ENUM</td></tr><tr><td>$table-&gt;float('amount', 8, 2);</td><td>相當於 FLOAT，可以指定總位數和小數位數</td></tr><tr><td>$table-&gt;geometry('positions');</td><td>相當於 GEOMETRY</td></tr><tr><td>$table-&gt;geometryCollection('positions');</td><td>相當於 GEOMETRYCOLLECTION</td></tr><tr><td>$table-&gt;increments('id');</td><td>遞增 ID（主鍵），相當於 UNSIGNED INTEGER</td></tr><tr><td>$table-&gt;integer('votes');</td><td>相當於 INTEGER</td></tr><tr><td>$table-&gt;ipAddress('visitor');</td><td>相當於 IP 地址</td></tr><tr><td>$table-&gt;json('options');</td><td>相當於 JSON</td></tr><tr><td>$table-&gt;jsonb('options');</td><td>相當於 JSONB</td></tr><tr><td>$table-&gt;lineString('positions');</td><td>相當於 LINESTRING</td></tr><tr><td>$table-&gt;longText('description');</td><td>相當於 LONGTEXT</td></tr><tr><td>$table-&gt;macAddress('device');</td><td>相當於 MAC 地址</td></tr><tr><td>$table-&gt;mediumIncrements('id');</td><td>遞增 ID（主鍵），相當於 UNSIGNED MEDIUMINT</td></tr><tr><td>$table-&gt;mediumInteger('votes');</td><td>相當於 MEDIUMINT</td></tr><tr><td>$table-&gt;mediumText('description');</td><td>相當於 MEDIUMTEXT</td></tr><tr><td>$table-&gt;morphs('taggable');</td><td>相當於加入遞增 UNSIGNED BIGINT 類型的 taggable\_id 與字串類型的 taggable\_type</td></tr><tr><td>$table-&gt;uuidMorphs('taggable');</td><td>相當於添加一個 CHAR (36) 類型的 taggable\_id 欄位和 VARCHAR (255) UUID 類型的 taggable\_type</td></tr><tr><td>$table-&gt;multiLineString('positions');</td><td>相當於 MULTILINESTRING</td></tr><tr><td>$table-&gt;multiPoint('positions');</td><td>相當於 MULTIPOINT</td></tr><tr><td>$table-&gt;multiPolygon('positions');</td><td>相當於 MULTIPOLYGON</td></tr><tr><td>$table-&gt;nullableMorphs('taggable');</td><td>添加一個可以為空版本的 morphs() 欄位</td></tr><tr><td>$table-&gt;nullableUuidMorphs('taggable');</td><td>添加一個可以為空版本的 uuidMorphs() 欄位</td></tr><tr><td>$table-&gt;nullableTimestamps(0);</td><td>timestamps() 方法的別名</td></tr><tr><td>$table-&gt;point('position');</td><td>相當於 POINT</td></tr><tr><td>$table-&gt;polygon('positions');</td><td>相當於 POLYGON</td></tr><tr><td>$table-&gt;rememberToken();</td><td>添加一個允許空值的 VARCHAR (100) 類型的 remember\_token 欄位</td></tr><tr><td>$table-&gt;set('flavors', \['strawberry', 'vanilla'\]);</td><td>相當於 SET</td></tr><tr><td>$table-&gt;smallIncrements('id');</td><td>遞增 ID（主鍵），相當於 UNSIGNED SMALLINT</td></tr><tr><td>$table-&gt;smallInteger('votes');</td><td>相當於 SMALLINT</td></tr><tr><td>$table-&gt;softDeletes('deleted\_at', 0);</td><td>相當於為軟刪除添加一個可為空值的 deleted\_at 欄位</td></tr><tr><td>$table-&gt;softDeletesTz('deleted\_at', 0);</td><td>相當於為軟刪除添加一個可為空值的帶時區的 deleted\_at 欄位</td></tr><tr><td>$table-&gt;string('name', 100);</td><td>相當於指定長度的 VARCHAR</td></tr><tr><td>$table-&gt;text('description');</td><td>相當於 TEXT</td></tr><tr><td>$table-&gt;time('sunrise', 0);</td><td>相當於指定位數的 TIME</td></tr><tr><td>$table-&gt;timeTz('sunrise', 0);</td><td>相當於指定位數帶時區的 TIME</td></tr><tr><td>$table-&gt;timestamp('added\_on', 0);</td><td>相當於指定位數的時間戳記</td></tr><tr><td>$table-&gt;timestampTz('added\_on', 0);</td><td>相當於指定位數帶時區的時間戳記</td></tr><tr><td>$table-&gt;timestamps(0);</td><td>相當於添加可為空值的時間戳記類型的 created\_at 和 updated\_at</td></tr><tr><td>$table-&gt;timestampsTz(0);</td><td>相當於添加指定時區的可為空值的時間戳記類型的 created\_at 和 updated\_at</td></tr><tr><td>$table-&gt;tinyIncrements('id');</td><td>相當於自動遞增 UNSIGNED TINYINT</td></tr><tr><td>$table-&gt;tinyInteger('votes');</td><td>相當於 TINYINT</td></tr><tr><td>$table-&gt;unsignedBigInteger('votes');</td><td>相當於 UNSIGNED BIGINT</td></tr><tr><td>$table-&gt;unsignedDecimal('amount', 8, 2);</td><td>相當於 UNSIGNED DECIMAL ，可以指定總位數和小數位數</td></tr><tr><td>$table-&gt;unsignedInteger('votes');</td><td>相當於 UNSIGNED INTEGER</td></tr><tr><td>$table-&gt;unsignedMediumInteger('votes');</td><td>相當於 UNSIGNED MEDIUMINT</td></tr><tr><td>$table-&gt;unsignedSmallInteger('votes');</td><td>相當於 UNSIGNED SMALLINT</td></tr><tr><td>$table-&gt;unsignedTinyInteger('votes');</td><td>相當於 UNSIGNED TINYINT</td></tr><tr><td>$table-&gt;uuid('id');</td><td>相當於 UUID</td></tr><tr><td>$table-&gt;year('birth\_year');</td><td>相當於 YEAR</td></tr></tbody></table>

[學習Laravel Migration，看這一篇就夠了 (pandalab.org)](https://pandalab.org/articles/105)

# Laravel queue 使用supervisor 實現多執行序

[https://segmentfault.com/a/1190000021165798](https://segmentfault.com/a/1190000021165798)

```
[program:laravel-queue-work]
process_name=%(program_name)s_%(process_num)02d
directory=/data/yoursite
command=php artisan queue:work
autostart=true
autorestart=true
user=www
numprocs=32
redirect_stderr=true
```

安裝supervisor

```shell
yum install -y supervisor
```

修改設定檔 vim /etc/supervisord.conf

```INI
[include]
files = supervisord.d/*.conf
;files = supervisord.d/*.ini 改成 files = supervisord.d/*.conf
```

新增 laravel-queue-work.conf

```shell
vim /etc/supervisord.d/laravel-queue-work.conf
```

```
[program:laravel-queue-work]
process_name=%(program_name)s_%(process_num)02d
directory=/usr/share/nginx/html/laravel5/webmon
command=php artisan queue:work
autostart=true
autorestart=true
user=nginx
numprocs=50
;stdout_logfile = /etc/supervisor.d/log/laravel-queue.log
;stderr_logfile = /etc/supervisor.d/log/laravel-queue_err.log
redirect_stderr=true

[supervisord]

```

常用指令

```shell
#執行 supervisor
#supervisord 
#supervisord -c /etc/supervisord.d/laravel-queue-work.conf (指令config)
[root@aaa]#  supervisord
/usr/lib/python2.7/site-packages/supervisor/options.py:461: UserWarning: Supervisord is running as root and it is searching for its configuration file in default locations (including its current working directory); you probably want to specify a "-c" argument specifying an absolute path to a configuration file for improved security.
  'Supervisord is running as root and it is searching '

#顯示執行 目前沒有執行
[root@a1-gcm12 etc]# supervisorctl status
unix:///var/run/supervisor/supervisor.sock no such file

#顯示執行 (目前執行)
[root@a1-gcm12 etc]# supervisorctl status
laravel-queue-work:laravel-queue-work_00   RUNNING   pid 28389, uptime 0:00:20
laravel-queue-work:laravel-queue-work_01   RUNNING   pid 28388, uptime 0:00:20
laravel-queue-work:laravel-queue-work_02   RUNNING   pid 28391, uptime 0:00:20



#修改設定檔後重新載入
[root@a1-gcm12 etc]# supervisorctl reload

#停用 supervisor
[root@aaa]# supervisorctl shutdown
Shut down


```

# Laravel Repository

[Day13-\[Laravel 資料夾目錄與內容\] Repository - iT 邦幫忙::一起幫忙解決難題，拯救 IT 人的一天 (ithome.com.tw)](https://ithelp.ithome.com.tw/articles/10205996)

# Laravel_解決CORS錯誤

已封鎖跨來源請求: 同源政策不允許讀取 http://192.168.1.1/api/XXXXXX 的遠端資源。（原因: 缺少 CORS 'Access-Control-Allow-Origin' 檔頭）

建立 app/Http/Middleware/Cors.php

```PHP
<?php

namespace App\Http\Middleware;

use Closure;

class Cors{
    public function handle($request, Closure $next)
    {
        return $next($request)->header('Access-Control-Allow-Origin', '*')
        ->header('Access-Control-Allow-Methods', '*')
        ->header('Access-Control-Allow-Headers', 'Origin, Methods, Content-Type, Authorization')
        ->header('Access-Control-Allow-Credentials', true);
    }

}

```

app/Http/Kenek.php

```PHP
protected $routeMiddleware = [
      //加入
        'cors' => \App\Http\Middleware\Cors::class,
    ];
protected $middlewarePriority = [
      //加入
        \App\Http\Middleware\Cors::class
    ];
```

路由加入middle ware

routes/api.php

```PHP
Route::group(['middleware' => 'cors'],function(){
    Route::match(['get','post'],'test/TestApi','TestController@TestApi');
});

```

# Laravel_log_permission

config/logging.php

```PHP
    'daily' => [
        'driver' => 'daily',
        'path' => storage_path('logs/laravel.log'),
        'level' => 'debug',
        'days' => 7,
        'permission' => 0664,
    ],
```

參考：[Laravel daily log created with wrong permissions | Newbedev](https://newbedev.com/laravel-daily-log-created-with-wrong-permissions)

# Laravel_Queue

[20分鐘學會Laravel的Queue功能 (pandalab.org)](https://www.pandalab.org/articles/107)

修改設定檔 env.php -&gt; 指定何種連接

queue.php 連接設定

[![image-1637202514068.png](https://bookstack.treemanou.com/uploads/images/gallery/2021-11/scaled-1680-/mL8DFlh054owdEE9-image-1637202514068.png)](https://bookstack.treemanou.com/uploads/images/gallery/2021-11/mL8DFlh054owdEE9-image-1637202514068.png)

[![image-1637202726195.png](https://bookstack.treemanou.com/uploads/images/gallery/2021-11/scaled-1680-/0ZD3mQBGlPv9OePm-image-1637202726195.png)](https://bookstack.treemanou.com/uploads/images/gallery/2021-11/0ZD3mQBGlPv9OePm-image-1637202726195.png)

建立table

```shell
# 建立 jobs table
php artisan queue:table
# 建立 failed-table
php artisan queue:failed-table

#  執行建立工作
php artisan migrate

```

建立job

```shell
#php artisan make:job {job name}
php artisan make:job TestGcm
```

# Laravel_Request

參考：

[學習LARAVEL 請求，看這一篇就夠了 (pandalab.org)](https://pandalab.org/articles/108)

# Laravel_Validation

參考:

[Laravel Validation 經驗談. 如何確認 request body的參數是符合我們預期的？… | by Kidd Chan | K88D | Medium](https://medium.com/kidd88/laravel-validation-%E7%B6%93%E9%A9%97%E8%AB%87-108902f61d09)

[Laravel 台灣翻譯文件 | Laravel 道場 (laravel-dojo.com)](https://docs.laravel-dojo.com/laravel/5.5/validation)

# 【Larvel】 redirect() 與 redirect()->intended()

在 Laravel 中，`redirect()->intended('/login')` 和 `redirect('/login')` 有一些差異，主要是用於不同的用途和情境：

1. **`redirect()->intended('/login')`**：
    
    
    - `intended()` 方法用於重定向到上一個受保護路由的預期 URL。這通常在使用中間件保護的路由中，當用戶未登入而被重定向到登入頁面時，用於指示登入成功後應該返回的路由。
    - 當用戶在未登入狀態下訪問一個需要登入才能訪問的路由時，系統會記錄下該受保護路由的 URL。當用戶成功登入後，使用 `redirect()->intended('/login')` 將用戶重定向到該受保護路由的 URL，這樣可以提供更好的使用者體驗。
    
    ```
    <span class="hljs-keyword">return</span> redirect<span class="hljs-function"><span class="hljs-params">()</span>-></span>intended(<span class="hljs-string">'/login'</span>);
    
    ```
2. **`redirect('/login')`**：
    
    
    - `redirect('/login')` 簡單地將用戶重定向到指定的 URL，這個 URL 可以是任何您希望將用戶重定向到的地方，例如登入頁面或任何其他頁面。
    
    ```
    <span class="hljs-function"><span class="hljs-keyword">return</span> <span class="hljs-title">redirect</span><span class="hljs-params">(<span class="hljs-string">'/login'</span>)</span></span>;
    
    ```

### 差異及適用情境：

- **使用 `redirect()->intended('/login')`**：
    
    
    - 主要用於處理登入成功後的重定向，確保用戶可以返回他們原本想要訪問但需要登入才能進入的頁面。
    - 通常與中間件（如 `auth` 中間件）結合使用，當用戶在未登入狀態下訪問受保護路由時會被重定向到登入頁面，成功登入後，會使用 `intended()` 方法將用戶重定向回原本要訪問的受保護路由。
- **使用 `redirect('/login')`**：
    
    
    - 簡單地將用戶重定向到指定的 URL，通常用於靜態的重定向，不涉及登入成功後的動態路由記錄和重定向。

### 總結：

使用 `redirect()->intended('/login')` 和 `redirect('/login')` 主要取決於您的需求。如果您需要確保用戶在成功登入後返回到原本要訪問的受保護路由，應使用 `intended()` 方法。而如果僅僅需要將用戶重定向到靜態的登入頁面或其他固定的 URL，則可以直接使用 `redirect('/login')`。

# Laravel 8 + Vue 3 專案建置（PHP 7.4 支援）

## 🔧 **專案名稱：DemoProject**

由於 PHP 7.4 無法使用 Vite，因此本指南使用 **Laravel Mix** 來配置 **Laravel 8 + Vue 3** 專案。

---

## ✅ **步驟 1：安裝 Laravel 8**

```bash
composer create-project laravel/laravel demo-project "8.*"
cd insure-next

```

啟動 Laravel 伺服器來確認專案正常運行：

```bash
php artisan serve

```

---

## ✅ **步驟 2：安裝 Vue 3**

在專案目錄下執行以下指令來安裝 Vue 3 和相關套件：

```bash
npm install vue@3 vue-loader@next

```

---

## ✅ **步驟 3：修改 Laravel Mix 設定**

開啟專案的 **`webpack.mix.js`**，修改如下：

```javascript
const mix = require('laravel-mix');

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

```

---

## ✅ **步驟 4：建立必要檔案**

1. **建立 `resources/js/app.js`**：

```javascript
import { createApp } from 'vue';
import App from './App.vue';

createApp(App).mount('#app');

```

2. **建立 `resources/js/App.vue`**：

```vue
<template>
    <div>
        <h1>Welcome to DemoProject!</h1>
    </div>
</template>

<script>
export default {
    name: 'App',
};
</script>

```

3. **建立 `resources/sass/app.scss`**（如果尚未建立）：

```bash
mkdir -p resources/sass

```

在 **`resources/sass/app.scss`** 中新增基本樣式：

```scss
body {
    font-family: Arial, sans-serif;
    background-color: #f8f9fa;
}

```

4. **建立 `resources/css/app.css`**（如果有純 CSS 檔案的需求）：

```css
/* app.css */
body {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

```

---

## ✅ **步驟 5：修改 Blade 模板**

將 **`resources/views/welcome.blade.php`** 修改為 **`resources/views/index.blade.php`**，內容如下：

```html

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>InsureNext</title>
    <link rel="stylesheet" href="{{ mix('css/app.css') }}">
</head>
<body>
    <div id="app"></div>

    <script src="{{ mix('js/app.js') }}"></script>
</body>
</html>

```

---

## ✅ **步驟 6：路由設定**

在 **`routes/web.php`** 中新增以下路由設定，將所有頁面導向 Vue 入口頁面：

```php
use Illuminate\Support\Facades\Route;

Route::get('/{any}', function () {
    return view('index');
})->where('any', '.*');

```

---

## ✅ **步驟 7：編譯資源**

執行以下指令來編譯前端資源：

```bash
npm run dev

```

若要進行生產環境的編譯，執行：

```bash
npm run production

```

---

## ✅ **錯誤排除 1：Module not found: Error: Can't resolve 'app.scss'**

如果你遇到以下錯誤：

```bash
Module not found: Error: Can't resolve 'resources/sass/app.scss'

```

請確保已建立 **`resources/sass/app.scss`**，或者修改 **`webpack.mix.js`**，移除 `sass` 編譯：

```javascript
const mix = require('laravel-mix');

mix.js('resources/js/app.js', 'public/js')
    .vue();

```

---

## ✅ **錯誤排除 2：Unable to locate Mix file: /css/app.css**

如果你遇到以下錯誤：

```bash
Unable to locate Mix file: /css/app.css

```

請依照以下步驟處理：

1. 確認資源已正確編譯：

```bash
npm run dev

```

2. 若問題仍未解決，清除 Laravel 快取：

```bash
php artisan config:clear
php artisan cache:clear
php artisan view:clear

```

3. 確認檔案 **`public/css/app.css`** 存在。如果不存在，執行以下指令重新建立檔案：

```bash
npm run dev

```

---

## ✅ **完成！**

現在你已經成功建置了一個 **Laravel 8 + Vue 3** 專案，專案名稱為 **InsureNext**。

Laravel 的路由設定已將所有頁面導向 **Vue 入口頁面**，並由 **Vue Router** 來處理前端頁面轉換。

</body></html>

# 【Laravel】部署在 SLB 或 Nginx 後面，要根據實際使用者請求是 HTTP 或 HTTPS

> 在 Laravel 中，當應用被部署在 **SLB 或 Nginx 後面**，要根據實際使用者請求是 HTTP 或 HTTPS，讓 Laravel 正確產生資源（asset/url）的協定 (`http://` 或 `https://`)，**同時支援兩種不同呼叫來源**（SLB 代理或 client 直連）。

---

## ✅ 關鍵目標：

Laravel 要根據 **實際瀏覽器請求的協定**（**而不是內部或 SLB 連線的協定**）來產生正確的資源連結。

---

## 🧠 為什麼 Laravel 判斷會錯？

當你部署在 **SLB 或 Nginx 反向代理**後面時，Laravel 實際收到的請求是從 SLB 傳來的，Laravel 預設只看：

```php
$_SERVER['HTTPS'] // on or off

```

這時它會誤以為是 HTTP，而不是使用者原本的 HTTPS。

---

## ✅ 正確作法：三步驟搞定 HTTP/HTTPS 自動判斷

---

### ✅ 步驟 1：設定 Laravel 的 TrustProxies

#### `app/Http/Middleware/TrustProxies.php`

```php
use Illuminate\Http\Request;
use Illuminate\Http\Middleware\TrustProxies as Middleware;

class TrustProxies extends Middleware
{
   protected $proxies = '*'; // 或指定你的 proxy IP

   // protected $headers = Request::HEADER_X_FORWARDED_ALL; // 此為舊方法已廢棄感用以下預設
  
   protected $headers =
        Request::HEADER_X_FORWARDED_FOR |
        Request::HEADER_X_FORWARDED_HOST |
        Request::HEADER_X_FORWARDED_PORT |
        Request::HEADER_X_FORWARDED_PROTO |
        Request::HEADER_X_FORWARDED_AWS_ELB;
}

```

---

### ✅ 步驟 2：讓 SLB 或 Nginx 傳遞 `X-Forwarded-Proto`

#### 📌 Nginx 範例（很關鍵）：

```nginx
location / {
    proxy_pass http://127.0.0.1:8000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;  # ⭐ 告訴 Laravel 真正協定是 http or https
}

```

#### 📌 AWS ALB / 阿里雲 SLB 也會自動加上 `X-Forwarded-Proto`，你只需要 Laravel 信任它即可（Step 1）

---

### ✅ 步驟 3：確認 `.env` 有設 APP\_URL（給 CLI 用）

```env
APP_URL=https://your-domain.com

```

Laravel CLI 執行時（如：`php artisan queue:work`）沒有 request context，會 fallback 使用 `APP_URL`。

---

## 🔍 驗證

在你的 Laravel 控制器或 middleware 中加這段：

```php
dd([
    'secure' => request()->isSecure(),
    'scheme' => request()->getScheme(),
    'url' => request()->fullUrl(),
]);

```

你應該會看到：

```php
[
  'secure' => true,
  'scheme' => 'https',
  'url' => 'https://your-domain.com/some/path'
]

```

或是在頁面上加上

```
 {{ request()->isSecure() ? 'HTTPS ✅' : 'HTTP ❌' }}
 <br>
 {{ url()->current() }}
 <br>
```

可以看到

[![image-1753348696262.png](https://bookstack.treemanou.com/uploads/images/gallery/2025-07/scaled-1680-/Pnl4rW1ATQlkG0UN-image-1753348696262.png)](https://bookstack.treemanou.com/uploads/images/gallery/2025-07/Pnl4rW1ATQlkG0UN-image-1753348696262.png)

如果前方沒有正確帶入(nginx 前面還有SLB)，可以手動寫死

```Nginx
proxy_set_header X-Forwarded-Proto https;
```

---

## ✅ 小結：Laravel 正確產生 HTTP 或 HTTPS 協定連結的條件

<table id="bkmrk-%E9%A0%85%E7%9B%AE-%E8%AA%AA%E6%98%8E-trustproxies-%E8%A8%AD"><thead><tr><th>項目</th><th>說明</th></tr></thead><tbody><tr><td>`TrustProxies` 設定</td><td>必須設為 `*` + `HEADER_X_FORWARDED_ALL`</td></tr><tr><td>Proxy 傳 `X-Forwarded-Proto`</td><td>Nginx / SLB 必須傳遞使用者實際協定</td></tr><tr><td>`.env` 的 `APP_URL`</td><td>CLI 模式需 fallback 使用，請設為 `https://...`</td></tr><tr><td>使用 Laravel 的 `asset()`, `url()`, `route()`</td><td>Laravel 會根據協定正確產生 URL</td></tr></tbody></table>

---