# Laravel 9.x DB 連線測試 多資料庫關聯 Login 模擬註冊 2022-01-04
###### tags: `Laravel` `Nginx` `Composer` `Web server` `Front end` `後端心得`
---
Laravel 有些後台頁面 demo 時 會用指令的方式來模擬註冊, 並新建一筆註冊資料在 table 上
## Laravel 支援多資料庫關聯~
要在 `.env` `database.php` 以及 Models 底下的 `Admin/User.php` `migrations/2023_01_04_xxxxxx_admin_test`, 以及 commands 做操作
**Models 以及 migrations 需要用指令操作:
```
php artisan make:model Admin/User
php artisan make:migration admin_test
```
----
## 1. 在 .env 檔案進行複製貼上
例如原本的 DB 相關連接設定:
```
# xxx_admin 後台多資料庫關聯 - 環境設定
DB_CONNECTION2=mysql -> 設定資料庫是 mysql
DB_HOST2=192.168.66.xx -> 設定虛擬機或其他位址
DB_PORT2=330x
DB_DATABASE2=xxx_admin -> 設定 admin 的 DB 名稱
DB_USERNAME2=xxxx -> 設定帳號
DB_PASSWORD2=xxxx -> 密碼
```
把它再複製一份寫在下面:
![](https://i.imgur.com/BNkQVXA.png)
---
## 2. 在 database.php 設定
這邊 laravel 會很細心地把常見的資料庫類型給預設寫在這, 例如 sqlite, mysql, pgsql
這邊以 mysql 作範例:
原本的預設值 ↓
```
'mysql' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
```
把它複製一份寫上來:
第二個資料庫的設定 ↓
```
// xxx_admin 後台多資料庫關聯
// env('xxx') 相關的名稱不要跟第一個資料庫一樣, 例如 env('DATABASE_URL2')
'mysql2' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL2'), // 設定資料庫位址, 偷懶的話可以寫URL2
'host' => env('DB_HOST2', '127.0.0.1'),
'port' => env('DB_PORT2', '3306'),
'database' => env('DB_DATABASE2', 'forge'), // 設定資料庫2
'username' => env('DB_USERNAME2', 'forge'), // 設定 admin 使用者
'password' => env('DB_PASSWORD2', ''), // 設定 admin 密碼
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
```
----
## 3. 在 Model 底下建一個 Admin/User
namespace 的話記得照著路徑走, 例如 `Models\Admin\User.php` 的話
```
namespace App\Models\Admin;
```
物件導向的 class 也要照著規範寫:
```
class User extends Model
{
use HasFactory;
protected $connection = 'mysql2';
protected $table = 'admin_test'; -> 根據 table 的名稱
protected $guarded = ['id']; -> 避免 id 被隨意輸入
protected $fillable = ['admin_test']; -> 代表這個 table 是可以被寫入的, 其他還有 email, password 等可以寫在這
// protected $fillable = ['name','password','created_at','updated_at'];
}
}
```
---
## 4. 在 migrations 中設定 table 遷移對應的方式
migrations 在 Laravel 中是一種資料庫的版本控制, 可以讓 team 快速修改和共享資料庫結構
一個 migrations 中的 class 會包含 `up()` 和 `down()` 兩種方法
可以在 up(中這樣寫):
```
Schema::connection('mysql2')->create('admin_test', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name', 32);
$table->string('email', 64)->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password')->unique();
$table->timestamps();
$table->smallInteger('role_id');
// $table->timestamp('admin_test')->nullable();
});
```
down() 中:
```
Schema::connection('mysql2')->drop('admin_test');
```
分別對應資料庫的架構
---
## 5. 建一個 Commands
在 Commands 底下用指令造一個 CreateAdmin.php:
```
php artisan make:command CreateAdmin
```
路徑記得引入
```
use App\Models\Admin\User;
```
指令的建構寫法:
```
class CreateAdmin extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'admin:create';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
// $email = $this->ask('請輸入email');
// while (User::where('email', $email)->exists()) {
// $this->info('email已存在');
// $email = $this->ask('請輸入email');
// }
// $password = $this->ask('請輸入密碼');
// User::create([
// 'email' => $email,
// 'password' => Hash::make($password),
// 'name' => 'admin' . now()->format('YmdHis'),
// 'role_id' => 1
// ]);
// $this->info('新增成功');
// 測試用指令, 輸入 php artisan admin:create 會直接在 DB 新建資料
User::create([
'admin_test' => now()
]);
return true;
}
}
```
## 6. 錯誤排除
`Add [admin_test] to fillable property to allow mass assignment on [App\Models\Admin\Login]`
→ 檢查 Models 底下的 Login 有沒有出現多個 class Login 的狀況, 記得不要復用
` Class "App\Models\Admin\User" not found`
→ 使用通靈的方式(x)去找這個 class 為啥不存在
使用指令 `php artisan migrate` 後出現:
```
SQLSTATE[HY000] [1045] Access denied for user 'root'@'192.168.66.xx' (using password: YES) (SQL: create table `admin_test` (`id` bigint unsigned not null auto_increment primary key, `created_at` timestamp null, `updated_at` timestamp null, `admin_test` timestamp null) default character set utf8mb4 collate 'utf8mb4_unicode_ci')
```
→ 去找 .env 和 database.php 有沒有設定錯誤, 或是跟某份資料庫共用到
==沒事千萬不要用`php artisan migrate:reset`==
這指令會還原所有遷移, 如果用 `migrate:refresh` 會還原遷移再執行 migrate
參考:
[Laravel資料庫遷移(migration)](https://ithelp.ithome.com.tw/articles/10220189)
---