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

匠人, 職人, 是指擁有某項熟練技巧, 手工一流的專業人員

  1. 測試專案開始

    建立新的測試專案

    安裝前置作業, 工具整備

    [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 ~ ]$

    工作目錄

    開發中, 習慣把的各種專案集中放在 ~/jobs/ 目錄裡, 這裡就是 `工作目錄`, 每個人可以依照自己的方式, 找個地方當作工作目錄. 在任何目錄之下都可以執行上面安裝 `Laravel Installer` 建立專案.
    如果在 ~/ 之下執行 laravel new testAuth, 它就會建立新的 ~/testAuth/ 專案.
    如果在 ~/abc/ 之下執行 laravel new testAuth, 它就會建立新的 ~/abc/testAuth/ 專案.
    如果在 /tmp/ 之下執行 laravel new testAuth, 它就會建立新的 /tmp/testAuth/ 專案.

    安裝命令及說明

    # 進入工作目錄(或自行建立新的子目錄)
    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 初始化並提交

    命令

    git init
    git st -s
    git add .
    git commit -m 'init testAuth'

    完成新的專案及 git

  2. 建立資料庫

    create db

    配合 .env 裡的設定, 進入 mysql 命令列, 以下 MYDATABASE, MYDBUSER, MYDBPASSWORD 請修改對應

    命令

    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 登入問題

    命令

    mysql -u MYDBUSER -p MYDATABASE
    php artisan migrate --seed

    執行結果

    [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 的方式, 建立資料使用者密碼.

  3. make:auth

    laravel 有內建的使用者帳號註册認證...等基本功能, 可以節省不少開發時間, 只要 php artisan make:auth 一鍵即可產生 auth 相關程式, 並用 git 觀察增加了那一些檔案.

    在命令列執行 make:auth

    命令

    # 產生 auth 相關程式
    php artisan make:auth
    # git 觀察增加了那一些檔案
    git st -s
    git add .
    git st -s

    執行結果

    [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.

    進入 瀏覽器 可以看到右上角多了 Login Register 兩個連結, 到目前為止, 很順利

  4. migrate 生成及遷移資料庫

    查看預設版本的 users 資料庫欄位, 並執行 migrate, 同時產生 seed

    在命令列執行 migrate --seed

    命令

    # 查看預設版本的 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

    執行結果

    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 檔案, 有一行程式碼

    $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).

    $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, 而不是逐次生成及遷移, 要小心使用, 重要 : 記得隨時先備份原有資料庫.

    命令

    php artisan migrate --seed
    php artisan migrate:fresh --seed # 重要 : 記得隨時先備份原有資料庫

    執行結果

    [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 ] $
  5. 網頁與資料庫第一次接觸

    第一次註冊

    重新遷移升級完成後, 進入 Register 頁面 測試, 照規則輸入簡單的註冊資訊, 按下提交. 好像沒那麼簡單...

    頁面錯誤訊息

    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 服務器, 再測試輸入註冊資訊, 果然成功.

    頁面訊息

    Dashboard
    You are logged in!

    檢查資料庫

    命令

    select * from users;

    執行結果

    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>
  6. 訊息在地中文化

    出現英文錯誤訊息

    回到頁面上 Logout (登出), 再進入 Register 重新註冊, 但仍使用 a@b.com 這個 email, 因為我們設定 email 為 unique, 會出現下列的錯誤訊息

    參考文件

    頁面訊息

    E-Mail Address
    The email has already been taken.

    訊息檔案目錄 resources/lang/

    為了要中文化, 我們要 cp -frp en zh-TW (先前修改系統基礎設定, 本地化 locale 預設 en, 改為 zh-TW) 整個子目錄.

    命令

    cd resources/lang/
    cp -frp en zh-TW
    ls
    cd zh-TW
    ls

    執行結果

    [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 這個檔案裡有一段

    'unique' => 'The :attribute has already been taken.',

    改成中文

    'unique' => ':attribute 已經存在。',

    存檔完成後, 返回瀏覽器註冊頁, 重試一次 email 欄位 a@b.com, 此刻會出現剛剛在地中文化之後的錯誤訊息. 傑克, 真是太神奇了...

    頁面訊息

    E-Mail Address
    email 已經存在。

    別忘了 git 一下

    git add .
    git commit -m 'Auth + 第一次在地中文化完成'
  7. 在地化的語言套件

    剛剛在 resources/lang/zh-TW/ 裡的那 4 個 php 檔案, 大約不到 200 個訊息字串, 不是很多. 逐一自行翻譯, 看起來不是苦差事, 但也不是好差事. 每次建造一台車子, 都要重新發明輪子, 這也真的太辛苦了, 還好有

    Laravel-lang 套件

    從網站的 README.md 得知安裝方式

    命令及說明

    # 安裝 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

    git add .
    git commit -m 'Auth + Laravel-lang 在地化的語言套件完成'
  8. 本章總結

    本章使用 laravel 命令總結

    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 在地化的語言套件