Laravel ORM Model 的預定義屬性
緣起
後端開發的基本操作就是處理資料 -- "增刪改查 / CURD", 而 Laravel 框架的"物件關係對映 (ORM = Object Relationship Mapping)" 為解決資料操作中的痛點和癢點提供了便捷的解決方案.
屬性
$table 屬性 -- 自定義關聯的資料表
既然叫"物件關係對映", 則意味著有明確的對應關係和約定.
Laravel 約定資料表的表名是 Model 名的複數, 比如 User Model 對應的是 users 表, Order Model 對應的是 orders 表.
如果需要自定義, 可以通過覆寫 $table
屬性來指定表名:
protected $table = 'yourTableName';
$primaryKey 屬性 -- 自定義主鍵
Laravel 約定每張表都有整型的 id
欄位做為自增主鍵.
如果想設定其他欄位做為主鍵,可以通過覆寫 $primaryKey
屬性來自定義.
protected $primaryKey = 'uid';
$timestamp 屬性 -- 資料的時間戳屬性
資料的可追溯性是非常重要的. 所以 Laravel 遷移檔案預設帶時間戳:
$table->timestamps();
所以通過遷移檔案生成的資料表預設帶 create_at
和 updated_at
欄位, 在新增資料和更新資料時會分別自動更新這兩個欄位.
這兩個欄位是 MySQL 的 datetime
型別, 即這種樣式: 2015-08-05 07:27:09
.
但是個人覺得從 MySQL 檢索優化的角度來說, int
型的 Unix 時間戳比 datetime
型別速度要快, 所以這樣設定:
use Illuminate\Database\Eloquent\Model;
class PosterSubScribeModel extends Model
{
protected $table = 'subscriber';
protected $guarded = [''];
/**
* 獲取當前Unix時間戳
* @return int
*/
public function freshTimestamp()
{
return time();
}
/**
* 避免轉換Unix時間戳為時間字串
*
* @param \DateTime|int $value
* @return \DateTime|int
*/
public function fromDateTime($value)
{
return $value;
}
}
PS. 如果不想使用
timestamp
, 可以將其關閉:
protected $timestamps = FALSE;
$casts 屬性 -- 轉化資料型別
PHP 擅長處理陣列, 而前後端互動通常用 JSON, 所以常見的場景是我們希望用"陣列"處理資料和儲存資料, 但是希望讀取出來的是 JSON 格式.
這種場景下就可以使用 $casts
屬性, 實現取出資料時自動轉化為 JSON 資料:
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected $casts = [
'my_array_data' => 'json',
];
}
還有一種使用場景, 是把儲存的 1 和 0, 在取出時自動轉化為 true 和 false:
class User extends Model
{
protected $casts = [
'options' => 'json',
'status' => 'bool',
];
}
**注意: **$cast
並沒有真的改變儲存的資料型別,而是取出資料時暫時轉換成設定的資料型別;
$attributes 屬性 -- 預設值
給資料庫裡的一個欄位設定預設值.
protected $attributes = [
'goods_ids' => '[]', //可以配合 $casts, 取出資料時自動轉化為 JSON
'category_ids' => '[]',
'display_order' => 0,
];
注意:
不能寫成 'goods_ids' => []
. 而必須給[]
加上引號; 上次因為沒有加引號, 儲存資料時莫名出現多個空資料(暫時還未弄清楚原因).
$dates 屬性 - 強大的時間類
時間資料經常面臨"格式化"的問題, 比如"Unix時間戳"和"可讀時間格式"的轉化.
$date
屬性可以解決這個問題.
設定成這個屬性的時間資料可以自動轉化為 Carbon 類的物件, 從而使用 Carbon 的方法來處理時間.
Carbon 類的方法很強大, 大家可以深入研究一下Carbon原始碼 或者是檢視 Laravel 中的 Carbon 類 (/vendor/nesbot/carbon/src/Carbon/Carbon.php).
比如, 把"可讀時間格式"(比如 2017-04-30 12:00) 轉化為 "Unix 時間戳":
$model->deleted_at->timestamp
$guarded 和 $fillable 屬性 -- 限制寫入資料庫的資料
因為 Eloquent 模型預設對批量賦值(Mass Assignment)進行保護. 這規則要求使用 create()
或者 update()
方法批量插入或者更新屬性時, 需要先設定 $guarded
和 $fillable
屬性.
設定後, 在批量寫入資料庫時, 不光會篩掉資料表沒有的欄位, 也會篩選掉 $guarded
和 $fillable
中限制的欄位.
-
$guarded
是"黑名單", 寫入這裡的欄位, 表示不可以被賦值; 如果所有欄位都可以寫入資料庫, 可以這樣寫protected $guarded = ['']
, 表示沒有需要被 "guarded/保護" 的欄位. -
$fillable
是"白名單", 寫入這裡的欄位, 表示只有在這些宣告的欄位可以被寫入資料庫;
注意:
一個 model 只能使用其中一個屬性, 而不是一起使用.
一般來說, 因為這兩個屬性的適用場景是剔除非法賦值的資料, 所以$guarded
使用的頻率高一些。
$hidden 和 $visible 屬性 -- 設定資料的可見性
比如像 password 這種欄位,是不希望在讀取後呈現給使用者看到的,那麼可以把它隱藏:
- 黑名單
$hidden
的寫法
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected $hidden = ['password'];
}
- 白名單
$visible
的寫法
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected $visible = ['first_name', 'last_name']; //排除 password 欄位
}
注意:
- 和
$guarded
&$fillable
屬性一樣, 一個 model 只能使用$hidden
和$visible
其中一個屬性, 而不是同時使用.
一般來說, 由於這兩個屬性的適用場景是"隱藏資料", 所以$hidden
使用的頻率高一些。 - 對於"關聯查詢"
- 如果要隱藏整張關聯表的欄位,需要在
$hidden
中填寫"表間關係的方法"(比如hasManyPost
) - 如果要隱藏關聯表裡的部分欄位,則需要到關聯表的 model 裡去設定
$hidden / $visible
屬性.
- 如果要隱藏整張關聯表的欄位,需要在
$appends 屬性 -- 新增屬性
開發 API 介面時, 前端經常會要求提供一些資料表沒有的欄位, 這時候, 就需要使用 $appends
屬性了. 在查詢資料庫返回的資料中, 手動增加新的資料:
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function getIsAdminAttribute()
{
return 'yes';
}
protected $appends = ['is_admin'];
}
這時, 查詢 users 表的資料時, 就多了一個 is_admin
的資料.
$deleted_at 屬性 -- 軟刪除
資料是寶貴的, 而硬碟儲存的成本非常低廉, 所以刪除資料時一般只是新增刪除標識而並不真的刪除資料.
Laravel 提供了"軟刪除"方案, 使用 deleted_at
欄位儲存資料的刪除時間. 查詢資料時, 被軟刪除的資料將會自動從查詢結果中排除.
想要使用"軟刪除", 需要這樣設定:
- 1.建立資料表時在"遷移檔案"中加入
deleted_at
欄位:
public function up()
{
Schema::table('flights', function ($table) {
$table->softDeletes();
});
}
或者是建立遷移檔案在已有的資料表中新增 deleted_at
欄位:
public function up()
{
Schema::table('poster', function (Blueprint $table) {
$table->integer('deleted_at')->nullable()->comment('刪除時間');
});
}
public function down()
{
Schema::table('poster', function (Blueprint $table) {
$table->dropColumn('deleted_at');
});
}
- 2.引入
SoftDeletes
的 trait, 並宣告deleted_at
欄位是$dates
屬性:
namespace App;
use app\common\models\BaseModel;
use Illuminate\Database\Eloquent\SoftDeletes;
class Poster extends BaseModel
{
use SoftDeletes;
protected $dates = ['deleted_at'];
}
如果想要查詢出這些被刪除的資料時, 只要加上 withTrashed()
方法即可.
參考文章
- Laravel 原始碼: .../vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php
- laravel--模型中各種屬性詳解
- Laravel 5.1 文件攻略 —— Eloquent: 讀取器和修飾器
- Laravel 5.1 文件攻略 —— Eloquent:模型物件序列化
- nesbot/carbon - A simple API extension for DateTime
文章歷史
- 2017/04/30 (第一次釋出)
- 2017/05/03 潤色
- 2017/06/03 潤色
- 2017/06/14 潤色
如果我的文章對你有用, 希望給些改進的建議, 或者打個"喜歡" _
相關文章
- Odoo ORM研究1 - BaseModel中的類屬性的作用OdooORM
- 定義物料型別的屬性型別
- Laravel ORM 對 Model::find 方法進行快取LaravelORM快取
- android中自定義屬性重複定義Android
- 定義一個巨大的model
- ts類中屬性定義的另一種方式
- Laravel 原始碼筆記 PHP 預定義介面 ArrayAccessLaravel原始碼筆記PHP
- [譯]Kotlin中是應該定義函式還是定義屬性?Kotlin函式
- Laravel 動態屬性的實現Laravel
- 跟蹤model中屬性(值)的變更
- Laravel 5.7 模型常用屬性Laravel模型
- laravel model自定義軟刪除欄位Laravel
- odoo ORM研究3 - odoo fields常用的欄位屬性OdooORM
- js如何獲取給定屬性的屬性值JS
- Xamarin Android提示找不到資源屬性定義Android
- C#給自動屬性設定預設值C#
- js如何獲取樣式表中定義的css屬性值JSCSS
- Laravel中的ModelLaravel
- Laravel_Model_Cache(針對快速更新的數值屬性進行快取優化的外掛)Laravel快取優化
- [踩坑]laravel 獲取一個model查詢結果中不存在的屬性返回NULLLaravelNull
- 結構體和類中屬性定義需要static地方結構體
- CSS 自定義屬性指北CSS
- data-* 自定義屬性
- Android自定義屬性Android
- css的border屬性預設值CSS
- 表屬性設定
- JavaScript設定屬性JavaScript
- jQuery設定disabled屬性與移除disabled屬性jQuery
- Xcode設定自己的個性屬性XCode
- 波哥學JAVA,定義類 宣告屬性 建立物件 例項化物件 物件呼叫屬性或者方法Java物件
- 結合元素和屬性的定義分析Schema的幾種設計方案
- model 與modelform屬性對應問題,誰幫幫我啊ORM
- dotnet C# 如何在頂級語句定義屬性C#
- 【譯】CSS 自定義屬性的策略指南CSS
- Hibernate的generator屬性之意義(轉)
- 使用預載入最佳化 Laravel Model 查詢Laravel
- CSS中常用的屬性設定CSS
- Gradle的屬性設定大全Gradle