# laravel 內建 Auth 功能實測 @ver 0.1.4 @date 2019-05-09 05:51:33 (星期四) @ver 0.1.3 @date 2019-03-12 10:58:21 (星期二) @ver 0.1.2 @date 2019-03-04 21:46:12 (星期一) @ver 0.1.1 @date 2019-03-02 12:05:52 (星期六) > **artisan** [wiki](https://zh.wikipedia.org/wiki/手工藝人) > > 匠人, 職人, 是指擁有某項熟練技巧, 手工一流的專業人員 999. ## 測試專案開始 ### 建立新的測試專案 #### 安裝前置作業, 工具整備 ```bash [alex@nvda ~ ]$ composer -V Composer version 1.8.4 2019-02-11 10:52:10 [alex@nvda ~ ]$ laravel -V bash: laravel:命令找不到 # 先用 composer 安裝 laravel install 到自己的 home 目錄之下 [alex@nvda ~ ]$ composer global require "laravel/installer" # 等待 ... 出現命令列提示符號 [alex@nvda ~ ]$ ll ~/.config/composer/vendor/bin/laravel lrwxrwxrwx 1 alex admin 28 3月 3 21:16 /home/alex/.config/composer/vendor/bin/laravel -> ../laravel/installer/laravel* # # # 把 bin 路徑加入 .profile vi ~/.profile # 跳到最後一行, 加入 PATH="$HOME/.config/composer/vendor/bin:$PATH" # 登出再登入 [alex@nvda ~ ]$ laravel -V Laravel Installer 2.0.1 [alex@nvda ~ ]$ ``` #### 工作目錄 ```plaintext 開發中, 習慣把的各種專案集中放在 ~/jobs/ 目錄裡, 這裡就是 `工作目錄`, 每個人可以依照自己的方式, 找個地方當作工作目錄. 在任何目錄之下都可以執行上面安裝 `Laravel Installer` 建立專案. 如果在 ~/ 之下執行 laravel new testAuth, 它就會建立新的 ~/testAuth/ 專案. 如果在 ~/abc/ 之下執行 laravel new testAuth, 它就會建立新的 ~/abc/testAuth/ 專案. 如果在 /tmp/ 之下執行 laravel new testAuth, 它就會建立新的 /tmp/testAuth/ 專案. ``` #### 安裝命令及說明 ```bash # 進入工作目錄(或自行建立新的子目錄) cd ~/jobs # 執行創立新的 laravel 套件命令, 有兩種方式 # 方式之一, 用 Laravel Installer, 執行 laravel new testAuth # 方式之二, 直接使用 composer , 執行 composer create-project --prefer-dist laravel/laravel testAuth # 等待約 60 秒, 出現命令列提示符號, 完成. 再進入專案的工作目錄 cd testAuth/ # 查看版本 php artisan -V # Laravel Framework 5.8.2 # 修改預設 .gitignore , 加入自已平常工作用的相關忽略文件 vi .gitignore # 修改資料連結的參數 vi .env # 用上面修改的參數, 到 mysql 建立資料庫, charset 用 utf8mb4 # (可不用修改, 使用預設 utf8mb4_unicode_ci) mysql 資料庫 collation 預設 utf8mb4_unicode_ci 改為 utf8mb4_general_ci # (可不用修改, 使用預設 utf8mb4_unicode_ci) vi config/database.php # 修改系統基礎設定, 時間 timezone 預設 UTC, 改為 Asia/Taipei # 修改系統基礎設定, 本地化 locale 預設 en, 改為 zh-TW vi config/app.php # 另外有一個 'fallback_locale' => 'en', 這個是指如果 'zh-TW' 找不到的話, 它要找誰的語言來替代顯示, 因為所有各種版本都一定有英文對應文字, 所以就用 'en' 即可, 改成 'zh-TW' 或其他語言也沒有什麼問題, 只是可能會顯示空白, 也許剛好可以拿來測試未翻譯本地化的文字. # (可暫時跳過) 修改 建立 自定義版本 log # (可暫時跳過) 自定義的單一日期時間 log 檔案, 每一次 request 產生一個記錄 # (可暫時跳過) 複製自定義 log class, app/Loggers/my1LocalLogger.php # (可暫時跳過) 複製自定義 json 輸出 class, app/Loggers/JsonFormatter.php vi config/logging.php # 啟動 laravel 內建 WEB 服務器, 預設 listen ip 為本機 127.0.0.1 , prot=8000, 可自定義, 只要不與原有或其他使用者互相衝突即可. 現在暫時用 2019 port 來啟動, 以下命令為本機 php artisan serve --port=2019 # 如果在雲端主機, 記得要加上 --host=nvda ( nvda 在 /etc/hosts 已指定 ip ), 把 listen ip 改為外部 ip 或 domain php artisan serve --host=nvda --port=2019 # 進入瀏覽器, 本機就用 http://127.0.0.1:2019, 雲端主機就用 http://www.nvda.org.tw:2019 或 http://172.104.76.106:2019 ``` ### git 初始化並提交 #### 命令 ```bash git init git st -s git add . git commit -m 'init testAuth' ``` 完成新的專案及 git 999. ## 建立資料庫 ### create db 配合 `.env` 裡的設定, 進入 mysql 命令列, 以下 `MYDATABASE, MYDBUSER, MYDBPASSWORD` 請修改對應 #### 命令 ```bash DROP DATABASE IF EXISTS MYDATABASE; CREATE DATABASE MYDATABASE DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; # mysql 5.7 以下可以使用 `WITH mysql_native_password` 或 `WITH sha256_password` 兩種不同的密碼加密方式, 若是 mysql 5.6 以下, 就把這兩個單字移除 CREATE USER 'MYDBUSER'@'localhost' IDENTIFIED WITH mysql_native_password BY 'MYDBPASSWORD'; GRANT ALL ON MYDATABASE.* TO 'MYDBUSER'@'localhost'; FLUSH PRIVILEGES; # 修改 USER 加密方式 ALTER USER 'MYDBUSER'@'localhost' IDENTIFIED WITH sha256_password BY 'MYDBPASSWORD'; ALTER USER 'MYDBUSER'@'localhost' IDENTIFIED WITH mysql_native_password BY 'MYDBPASSWORD'; ``` ### sha256_password 登入問題 #### 命令 ```bash mysql -u MYDBUSER -p MYDATABASE php artisan migrate --seed ``` #### 執行結果 ```shell [alex@nvda ~/jobs/testAuth ]$ mysql -u MYDBUSER -p MYDATABASE Enter password: ERROR 2061 (HY000): Authentication plugin 'sha256_password' reported error: Authentication requires SSL encryption [alex@nvda ~/jobs/testAuth ]$ [alex@nvda ~/jobs/testAuth ]$ php artisan migrate --seed PDOException : SQLSTATE[HY000] [2006] MySQL server has gone away at /home/alex/jobs/testAuth/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php:70 66| if (class_exists(PDOConnection::class) && ! $this->isPersistentConnection($options)) { 67| return new PDOConnection($dsn, $username, $password, $options); 68| } 69| > 70| return new PDO($dsn, $username, $password, $options); 71| } ``` 如果 `CREATE USER` 時使用 `sha256_password`, 在登入出現 `ERROR 2061 (HY000): Authentication plugin 'sha256_password' reported error: Authentication requires SSL encryption` 時必須使用 SSL 執行 `php artisan migrate --seed` 也會出現 `PDOException : SQLSTATE[HY000] [2006] MySQL server has gone away` 的錯誤訊息 用新的 mysql 8 版本測試, 完全沒問題, 可能是此版本 (mysql 5.7.25) 沒有把 ssl 套件包進去, 或者要另做其他處理 如果碰到此問題, 先暫時使用 `IDENTIFIED WITH mysql_native_password` 的方式, 建立資料使用者密碼. 999. ## make:auth laravel 有內建的使用者帳號註册認證...等基本功能, 可以節省不少開發時間, 只要 `php artisan make:auth` 一鍵即可產生 auth 相關程式, 並用 git 觀察增加了那一些檔案. ### 在命令列執行 make:auth #### 命令 ```bash # 產生 auth 相關程式 php artisan make:auth # git 觀察增加了那一些檔案 git st -s git add . git st -s ``` #### 執行結果 ```shell [alex@nvda ~/jobs/testAuth ] $ php artisan make:auth Authentication scaffolding generated successfully. [alex@nvda ~/jobs/testAuth ] $ [alex@nvda ~/jobs/testAuth ] $ git st -s M routes/web.php ?? app/Http/Controllers/HomeController.php ?? resources/views/auth/ ?? resources/views/home.blade.php ?? resources/views/layouts/ [alex@nvda ~/jobs/testAuth ] $ git add . [alex@nvda ~/jobs/testAuth ] $ git st -s A app/Http/Controllers/HomeController.php A resources/views/auth/login.blade.php A resources/views/auth/passwords/email.blade.php A resources/views/auth/passwords/reset.blade.php A resources/views/auth/register.blade.php A resources/views/auth/verify.blade.php A resources/views/home.blade.php A resources/views/layouts/app.blade.php M routes/web.php [alex@nvda ~/jobs/testAuth ] $ ``` 此命令修改了 `routes/web.php`. 增加了 8 個檔案, 其中包含 7 個 view 檔案, 以及一個 `app/Http/Controllers/HomeController.php`. 進入 [瀏覽器](http://127.0.0.1:2019) 可以看到右上角多了 `Login` `Register` 兩個連結, 到目前為止, 很順利 999. ## migrate 生成及遷移資料庫 查看預設版本的 users 資料庫欄位, 並執行 migrate, 同時產生 seed ### 在命令列執行 migrate --seed #### 命令 ```bash # 查看預設版本的 users 資料庫欄位 vi database/migrations/2014_10_12_000000_create_users_table.php vi database/migrations/2014_10_12_100000_create_password_resets_table.php # 執行 migrate php artisan migrate --seed ``` #### 執行結果 ```shell Illuminate\Database\QueryException : SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQL: alter table `users` add unique `users_email_unique`(`email`)) ``` ### mysql index 錯誤處理 出現了一個很頑固且常見的錯誤, 這跟 laravel 無關, 看看 `2014_10_12_000000_create_users_table.php` 檔案, 有一行程式碼 ```php $table->string('email')->unique(); ``` string() 代表 varchar(), 若沒有指定長度, 預設是 varchar(255), 因為我們指定它為 unique(), 所以建立資料庫時會產生一行指令 `unique users_email_unique(email)`. mysql charset 為 utf8mb4. 每個字是 4 bytes , 4 X 255 = 1020 bytes, 超過 mysql 預設的最大長度 766 bytes. 所以要修改 email 的長度為 190 ( 4 X 190 = 760). ```php $table->string('email', 190)->unique(); ``` 另一個檔案 `2014_10_12_100000_create_password_resets_table.php` 裡的 email 欄位也一樣狀況, 改長度為 190. 修改完成後 migrate , 如果又出現錯誤, 可能是先前升級一半, 沒有完成, 舊的 table 還在. ### 重新生成及遷移資料庫 > `migrate` 逐次生成及遷移, 它會查詢資料庫裡的 `migrations` table, 比對日期時間檔名, 未遷移檔案裡的欄位用 alter 加入 table. > > `migrate:fresh` 放下一切, 重新做人. 它會 `DROP` 所有 table, 然後 create 新的 table, 而不是逐次生成及遷移, 要小心使用, **重要 : 記得隨時先備份原有資料庫**. #### 命令 ```bash php artisan migrate --seed php artisan migrate:fresh --seed # 重要 : 記得隨時先備份原有資料庫 ``` #### 執行結果 ```shell [alex@nvda ~/jobs/testAuth ] $ php artisan migrate --seed Migrating: 2014_10_12_000000_create_users_table Illuminate\Database\QueryException : SQLSTATE[42S01]: Base table or view already exists: 1050 Table 'users' already exists ........ [alex@nvda ~/jobs/testAuth ] $ php artisan migrate:fresh --seed Dropped all tables successfully. Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table Database seeding completed successfully. [alex@nvda ~/jobs/testAuth ] $ ``` 999. ## 網頁與資料庫第一次接觸 ### 第一次註冊 重新遷移升級完成後, 進入 [Register 頁面](http://127.0.0.1:2019/register) 測試, 照規則輸入簡單的註冊資訊, 按下提交. 好像沒那麼簡單... #### 頁面錯誤訊息 ```bash ReflectionException (-1) Class setEventDispatcher does not exist ``` 這個時候, 先重新啟動 WEB 服務器. 遇到任何問題, 第一個考慮的方式 ... :-D 回到命令列, 用 Ctrl+C 結束先前執行的 `php artisan serve --port=2019`. 結束之後, 再重新執行一次, 問題依然發生. google 很久很久才找到 `This is a known PHP 7.3.0 bug. You should update your PHP version (ideally to 7.3.2).` 也許 7.3.0 之前不會有問題, 所以請大家先試試看, 若出現相同問題, 再考慮升級為最新版本(7.3.2 以後). #### (可跳過) mac 升級 php 7.3.0 為 7.3.2 ``` [alex] $ brew install php@7.3 Error: php 7.3.0_1 is already installed To upgrade to 7.3.2, run `brew upgrade php` ==> `brew cleanup` has not been run in 30 days, running now... Error: Permission denied @ unlink_internal - /usr/local/lib/node_modules/electron-prebuilt/dist/Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Libraries/Libraries [alex] $ brew upgrade php Updating Homebrew... ==> Upgrading 1 outdated package: php 7.3.0_1 -> 7.3.2 ... [alex] $ php -v PHP 7.3.2 (cli) (built: Feb 14 2019 10:08:45) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.3.2, Copyright (c) 1998-2018 Zend Technologies with Zend OPcache v7.3.2, Copyright (c) 1999-2018, by Zend Technologies ``` 升級完成, 重新啟動 WEB 服務器, 再測試輸入註冊資訊, 果然成功. #### 頁面訊息 ```shell Dashboard You are logged in! ``` ### 檢查資料庫 #### 命令 ```sql select * from users; ``` #### 執行結果 ```shell mysql> select * from users; +----+------+---------+-------------------+--------------------------------------------------------------+----------------+---------------------+---------------------+ | id | name | email | email_verified_at | password | remember_token | created_at | updated_at | +----+------+---------+-------------------+--------------------------------------------------------------+----------------+---------------------+---------------------+ | 1 | aa | a@b.com | NULL | $2y$10$zEoyfDL/uTp4ScResbMx/uQbzObWsIy/dhkD115yoiVbJ72GW4fQO | NULL | 2019-03-02 15:59:27 | 2019-03-02 15:59:27 | +----+------+---------+-------------------+--------------------------------------------------------------+----------------+---------------------+---------------------+ 1 row in set (0.00 sec) mysql> ``` 999. ## 訊息在地中文化 ### 出現英文錯誤訊息 回到頁面上 Logout (登出), 再進入 Register 重新註冊, 但仍使用 a@b.com 這個 email, 因為我們設定 email 為 unique, 會出現下列的錯誤訊息 [參考文件](https://docs.laravel-dojo.com/laravel/5.2/localization) #### 頁面訊息 ```shell E-Mail Address The email has already been taken. ``` ### 訊息檔案目錄 resources/lang/ 為了要中文化, 我們要 `cp -frp en zh-TW` (先前修改系統基礎設定, 本地化 locale 預設 en, 改為 zh-TW) 整個子目錄. #### 命令 ```bash cd resources/lang/ cp -frp en zh-TW ls cd zh-TW ls ``` #### 執行結果 ```shell [alex@nvda ~/jobs/testAuth ] $ cd resources/lang/ [alex@nvda ~/jobs/testAuth/resources/lang ] $ cp -frp en zh-TW # 有兩個子目錄 [alex@nvda ~/jobs/testAuth/resources/lang ] $ ls en zh-TW [alex@nvda ~/jobs/testAuth/resources/lang ] $ cd zh-TW/ # 有 4 個 php 檔案 [alex@nvda ~/jobs/testAuth/resources/lang/zh-TW ] $ ls auth.php pagination.php passwords.php validation.php ``` ### 第一次中文化就上手 在 `resources/lang/zh-TW/validation.php` 這個檔案裡有一段 ```php 'unique' => 'The :attribute has already been taken.', ``` 改成中文 ```php 'unique' => ':attribute 已經存在。', ``` 存檔完成後, 返回瀏覽器註冊頁, 重試一次 `email` 欄位 `a@b.com`, 此刻會出現剛剛在地中文化之後的錯誤訊息. 傑克, 真是太神奇了... #### 頁面訊息 ```shell E-Mail Address email 已經存在。 ``` #### 別忘了 git 一下 ```bash git add . git commit -m 'Auth + 第一次在地中文化完成' ``` 999. ## 在地化的語言套件 剛剛在 `resources/lang/zh-TW/` 裡的那 4 個 php 檔案, 大約不到 200 個訊息字串, 不是很多. 逐一自行翻譯, 看起來不是苦差事, 但也不是好差事. 每次建造一台車子, 都要重新發明輪子, 這也真的太辛苦了, 還好有 [Laravel-lang 套件](https://github.com/caouecs/Laravel-lang) 從網站的 README.md 得知安裝方式 #### 命令及說明 ```shell # 安裝 caouecs/laravel-lang # Laravel 5.8 composer require caouecs/laravel-lang:~4.0 # Laravel 5.1-5.7 composer require caouecs/laravel-lang:~3.0 # 等待約 60 秒, 出現命令列提示符號, 查看 ls vendor/caouecs/laravel-lang/src/zh-TW/ # 有 4 個 php 檔案 auth.php pagination.php passwords.php validation.php # 複製這 4 個已在地中文化的 php 檔案到實際運作的 resources/lang/zh-TW/ cp -f vendor/caouecs/laravel-lang/src/zh-TW/* resources/lang/zh-TW/ # 或 cp -fRp vendor/caouecs/laravel-lang/src/zh-TW resources/lang/ # 查看是否正確 vi resources/lang/zh-TW/validation.php # 補充-1 @date 2019-05-09 21:17:56 (星期四) # 還有一個主要的檔案 json 也要複製, 這個檔案包含很多基本語句本地化 cp vendor/caouecs/laravel-lang/json/zh-TW.json resources/lang/ ``` > 補充-1 說明 > > 還有一個主要的檔案 json 也要複製, 這個檔案包含很多基本語句本地化, 例如 `resources/views/auth/login.blade.php` 裡有 `{{ __('Login') }}`, 在英文版本正常狀態下, 會在瀏覽器上顯示 `Login` 這五個英文字, 先前忘了複製這個檔案, 所以即使我們在 `config/app.php` 裡設定 'locale' => 'zh-TW', 它還是顯示為英文的 `Login`. > > `vendor/caouecs/laravel-lang/json/zh-TW.json` 複製完成之後, 再更新網頁, 已經看到 `登入` 中文本地化的文字. 返回瀏覽器註冊頁, 嘗試各種錯誤, 讓它顯示在地中文化之後的任何訊息. 如果看到這個版本的中文太糟糕, 隨時自己動手修改這幾個 php 檔, 改成感覺良好的中文訊息. #### git ```bash git add . git commit -m 'Auth + Laravel-lang 在地化的語言套件完成' ``` 1000. ## 本章總結 ### 本章使用 laravel 命令總結 ```bash composer global require ... # composer 到 home 目錄下 laravel new project # 建立 laravel 專案 php artisan serve # 啟動內建 WEB 服務器 php artisan serve --port=2019 # 啟動內建 WEB 服務器 php artisan serve --host=nvda --port=2019 # 啟動內建 WEB 服務器 php artisan make:auth # 產生 auth 使用者帳號註册 php artisan migrate --seed # 生成及遷移資料庫 php artisan migrate:fresh --seed # 完整重新生成及遷移資料庫 resources/lang/ # 訊息在地中文化 composer require caouecs/laravel-lang:~3.0 # Laravel-lang 在地化的語言套件 ```