前一篇介紹了如何運用 Laravel 框架設計模式規劃大型專案,當中有提到Model,今天就來介紹這個Laravel Eloquent ORM.
開始前我們可以先把原先Laravel預設幫我們建立的migration和Model刪除或是直接改動檔案內容,才不會導致建立重複的檔案
首先要知道每個資料表要對應一個Model,所以當我們要一個User table,可以直接這樣下指令
$ sail artisan make:model User --migration
可以看到資料夾中建立了兩個檔案,
/database/migration中的2021_09_07_151450_create_users_table.php,migration指的就是資料庫的版本控制,透過新增migration檔案來操作資料庫的新增、修改、刪除,可以讓我們就算不同人進行開發,也能確保資料庫可以得到同步.我們先在該檔案的up()處輸入我們想建立的欄位,範例為建立User資料表,欄位為使用者姓名、帳號、密碼及啟用狀態,並在down()處設定刪除此資料表
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name')->comment('姓名');
            $table->string('account')->unique()->comment('帳號');
            $table->string('password')->comment('密碼');
            $table->boolean('enabled')->default(true)->comment('啟/停用');
            $table->timestamps();
        });
    }
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
}
當在建立時可以指定該欄位的狀態,比方說唯一性、註解、預設值...,以下列出幾個常見的
->unique()
->after('column')
->comment('my comment')
->default($value)
->nullable($value = true)
另外欄位的型態設定可以參考官方文件.
接下來在comand-line下指令就可以建立出我們的table,會執行所有未完成的migration up()
$ sail artisan migrate
如果想回滾(rollback)資料庫,則可以使用以下指令,範例為rollback到最近的一次遷移:
$ php artisan migrate:rollback --step=1
App/Models/User.php,我們依靠它來跟我們的Users資料表作溝通,<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
    /**
     * 指定哪些欄位可以存取
     *
     * @var array
     */
    protected $fillable = [
        'name',
        'account',
        'password',
    ];
    
    /**
     * 將資料作轉換
     *
     * @var array
     */
    protected $casts = [
        'enabled' => 'boolean',
        'created_at' => 'datetime:Y-m-d H:i:s',
        'updated_at' => 'datetime:Y-m-d H:i:s'
    ];
}
以下介紹幾個Model常見的屬性
/**
 * 替 model 指定 table
 *
 * @var string
 */
 protected $table = 'users';
Tip: Model會預設去找Model name + s的資料表.
/**
 * 白名單,可以被批量賦值的欄位
 *
 * @var array
 */
 protected $fillable = ['name', 'age'];
/**
  * 黑名單,不可被批量賦值的欄位,當guarded為空陣列,代表所有欄位皆可賦值,fillable與guarded擇一即可
  *
  * @var array
  */
 protected $guarded = ['id'];
詳細說明:
由於我們有時候為求方便直接用以下方式進行寫入,代表我們所有request代入的的payload都進行欄位的update,有些不想被修改的欄位就會被直接改動,例如id欄位,所以為了安全性要記得設定$fillable或$guarded
$post = Post::create($request->all());
/**
 * 將資料屬性做轉換
 *
 * @var array
 */
protected $casts = [
    'enabled' => 'boolean',
    'created_at' => 'datetime:Y-m-d H:i:s',
    'updated_at' => 'datetime:Y-m-d H:i:s'
];
詳細說明:
當資料庫的資料儲存為0或1時,設定casts enabled為boolean,會將資料進行轉換,當我們用Postman取出資料時,該值會轉換為boolean,是非常方便的功能

介紹並設定完Model後,我們要在Repository使用它,Exception的部分我想另外寫一篇文章介紹我們該怎麼處理它
<?php
namespace App\Repositories;
use Exception;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
class UserRepository
{
    /**
     * 透過帳號搜尋特定使用者
     *
     * @param string $account 帳號
     * @return mixed
     */
    public function searchUserByAccount(string $account)
    {
        try {
            return User::select(['*'])
                ->where('account', $account)
                ->first();
        } catch (Exception $e) {
            dd($e);
        }
    }
    /**
     * 取得使用者
     *
     * @param int $limit 帳號
     * @return mixed
     */
    public function getUserPaginate(int $limit)
    {
        try {
            return User::paginate($limit);
        } catch (Exception $e) {
            dd($e);
        }
    }
    /**
     * 建立使用者
     *
     * @param array $data
     * @return mixed
     */
    public function registerAccount(string $name, string $account, string $password)
    {
        try {
            return User::create([
                'name' => $name,
                'account' => $account,
                'password' => Hash::make($password),
            ]);
        } catch (Exception $e) {
            dd($e);
        }
    }
}
如此一來我們已經完成Model和Repository的撰寫,在後續文章會介紹如何在Service注入Repository,並使用這些function.