Laravel之ORM总结
# 时间戳
默认情况下,Eloquent期望created_at
和updated_at
已经存在于数据表中,如果你不想要这些Laravel自动管理的数据列,在模型类中设置$timestamps
属性为false
:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* 表明模型是否应该被打上时间戳
*
* @var bool
*/
public $timestamps = false;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
如果你需要自定义时间戳格式,设置模型中的$dateFormat
属性。该属性决定日期被如何存储到数据库中,以及模型被序列化为数组或JSON时日期的格式:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* 模型日期列的存储格式
*
* @var string
*/
protected $dateFormat = 'U';
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
如果你需要自定义用于存储时间戳的字段名称,可以在模型中设置CREATED_AT
和UPDATED_AT
常量:
<?php
class Flight extends Model
{
const CREATED_AT = 'creation_date';
const UPDATED_AT = 'last_update';
}
2
3
4
5
6
7
# 数据库连接
默认情况下,所有的Eloquent模型使用应用配置中的默认数据库连接,如果你想要为模型指定不同的连接,可以通过$connection
属性来设置:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* The connection name for the model.
*
* @var string
*/
protected $connection = 'connection-name';
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 默认属性值
如果你想要定义某些模型属性的默认值,可以在模型上定义$attributes
属性:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* The model's default values for attributes.
*
* @var array
*/
protected $attributes = [
'delayed' => false,
];
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 检查属性修改
Eloquent 提供了isDirty
、isClean
和wasChanged
方法来检查模型的内部状态并判断它的属性如何从初始加载状态发生改变。
isDirty
方法会判断模型从加载之后是否有任何属性发生改变,你可以传递特定属性名进行判断,isClean
方法和isDirty
方法作用相反,也支持传入可选的属性参数:
$user = User::create([
'first_name' => 'Taylor',
'last_name' => 'Otwell',
'title' => 'Developer',
]);
$user->title = 'Painter';
$user->isDirty(); // true
$user->isDirty('title'); // true
$user->isDirty('first_name'); // false
$user->isClean(); // false
$user->isClean('title'); // false
$user->isClean('first_name'); // true
$user->save();
$user->isDirty(); // false
$user->isClean(); // true
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
wasChanged 方法用于判断在当前请求生命周期内模型最后一次保存后是否有任何属性发生改变,你可以传递属性名来查看特定属性是否改变过:
$user = User::create([
'first_name' => 'Taylor',
'last_name' => 'Otwell',
'title' => 'Developer',
]);
$user->title = 'Painter';
$user->save();
$user->wasChanged(); // true
$user->wasChanged('title'); // true
$user->wasChanged('first_name'); // false
2
3
4
5
6
7
8
9
10
11
12
# fillable/guarded属性
可以使用create
方法保存一个新的模型, 该方法返回被插入的模型实例。但是,在此之前,你需要指定模型的fillable
或guarded
属性,因为所有Eloquent
模型都通过批量赋值(Mass Assignment)进行保护,这两个属性分别用于定义哪些模型字段允许批量赋值以及哪些模型字段是受保护的,不能显式进行批量赋值。
# 复制模型
可以通过replicate
方法创建一个模型实例的未保存副本,这在多个模型实例共享相同属性值时非常有用:
$shipping = App\Models\Address::create([
'type' => 'shipping',
'line_1' => '123 Example Street',
'city' => 'Victorville',
'state' => 'CA',
'postcode' => '90001',
]);
$billing = $shipping->replicate()->fill([
'type' => 'billing'
]);
$billing->save();
2
3
4
5
6
7
8
9
10
11
12
13
# 访问器和修改器
访问器和修改器允许你在获取模型属性或设置其值时格式化 Eloquent 属性。例如,你可能想要使用 Laravel 加密器对存储在数据库中的数据进行加密,并且在 Eloquent 模型中访问时自动进行解密。
# 定义访问器
要定义一个访问器,需要在模型中创建一个 getFooAttribute 方法,其中 Foo 是你想要访问的字段名(使用驼峰式命名规则)。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* 获取用户的名字
*
* @param string $value
* @return string
*/
public function getFirstNameAttribute($value)
{
return ucfirst($value);
}
}
// first_name 字段的原生值被传递给访问器,然后返回处理过的值。要访问该值只需要简单访问 first_name 即可
$user = App\Models\User::find(1);
$firstName = $user->first_name;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 修改器
定义一个修改器,需要在模型中定义 setFooAttribute 方法,其中 Foo 是你想要访问的字段(使用驼峰式命名规则).
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* 设置用户的名字
*
* @param string $value
* @return string
*/
public function setFirstNameAttribute($value)
{
$this->attributes['first_name'] = strtolower($value);
}
}
$user = App\Models\User::find(1);
$user->first_name = 'Sally'; // setFirstNameAttribute 方法会被调用,传入参数为 Sally,修改器会对其调用 strtolower 函数并将处理后的值设置为内部属性的值
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 日期修改器
默认情况下,Eloquent 将会转化created_at
和updated_at
列的值为Carbon
实例。默认情况下,时间戳的格式是 'Y-m-d H:i:s',如果你需要自定义时间戳格式,在模型中设置 $dateFormat 属性,该属性决定日期属性存储在数据库以及序列化为数组或 JSON 时的格式。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* 模型日期的存储格式
*
* @var string
*/
protected $dateFormat = 'U';
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 属性转换
模型中的$casts
属性为属性字段转换到通用数据类型提供了便利方法 。$casts
属性是数组格式,其键是要被转换的属性名称,其值时你想要转换的类型。目前支持的转换类型包括:integer
, real
, float
, double
, decimal:<digits>
, string
, boolean
, object
,array
,collection
,date
,datetime
和 timestamp
, 转化为decimal
时,必须定义数字的位数(decimal:2)
。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* 应该被转化为原生类型的属性
*
* @var array
*/
protected $casts = [
'is_admin' => 'boolean', // 转换 is_admin 属性,将其由 integer 值(0或1)转换为 boolean 值
];
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
注:值为 null 的属性不会被转化,此外,不要定义和关联关系同名的转化(或者属性)
# 不常用方法
# insertUsing
self::db($partition)->insertUsing(
['date', 'player_id', 'rank', 'updated_at'],
self::db($partition)->where('date', 0)->selectRaw("$date, player_id, `rank`, updated_at"),
);
2
3
4
# rename
Schema::rename($formalTable, $formalTable . '_past_' . date('ymdHi'));
Schema::rename($tmpTable, $formalTable);
2
# 原始表达式
有时你需要在查询中使用原始表达式,例如实现** COUNT(0) AS count**,这就需要用到raw方法。
use Hyperf\DbConnection\Db;
$res = Db::table('user')->select('gender', Db::raw('COUNT(0) AS `count`'))->groupBy('gender')->get();
2
3
# 常见问题
# firstOrCreate/firstOrNew区别
firstOrCreate
和firstOrNew
都可以用来创建模型。firstOrCreate
方法先尝试通过给定列/值对在数据库中查找记录,如果没有找到的话则通过给定属性创建一个新的记录。firstOrNew
方法和firstOrCreate
方法一样先尝试在数据库中查找匹配的记录,如果没有找到,则返回一个新的模型实例。需要注意的是,通过firstOrNew
方法返回的模型实例并没有持久化到数据库中,你还需要调用save
方法手动持久化。
# updateOrCreate/updateOrInsert区别
updateOrCreate()
和updateOrInsert()
两个方法都是用来保存数据的时候方便操作“存在即更新,反之则创建updateOrCreate()
方法使用的是 Eloquent ORM 操作的数据库(支持自动添加创建和更新时间),updateOrInsert()
方法使用的是查询构造器(不可以自动添加创建和更新时间)updateOrCreate()
返回值是\Illuminate\Database\Eloquent\Model
, updateOrInsert 返回的是bool