0%

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
<?php

namespace Illuminate\Database\Eloquent;

/**
* 下面提到某些词的含义:
* 1、覆盖: 在继承该类 \Illuminate\Database\Eloquent\Model 的自定义的模型类中, 定义一个同名 field,值不一样
*/
abstract class Model1 implements ArrayAccess, Arrayable, Jsonable, JsonSerializable, QueueableEntity, UrlRoutable
{
/**
* 数据库连接,我们在 config/database.php 里面的 connections 数组定义的连接。
* usage:
* (new xxModel)->connection('mysql')
* DB::connection('pgsql')
* 或者在模型定义里面覆盖该属性,如: protected $connection = 'pgsql';
*/
protected $connection;

/**
* 模型关联的数据库表名,默认是 模型名->下划线命名->复数形式,
* 好比如定义了 User 模型,class User extend Model,那么默认的表名是 users。
*
* usage:
* (new xxModel)->setTable('xxx')
* (new xxModel)->getModel()
* 或者在模型定义的时候覆盖该属性,如: protected $table = 'tb_user';
*/
protected $table;

/**
* 主键字段,默认为 id,也可以覆盖该属性
*/
protected $primaryKey = 'id';

/**
* 不知道哪里用到,除了该文件的 getter 和 setter
*/
protected $perPage = 15;

/**
* 主键是否默认自增长
*/
public $incrementing = true;

/**
* 是否由模型去维护时间戳字段,如果我们想手动去维护,可以设置为 false
* usage:
* 默认的时间戳字段是 created_at、updated_at,
* 我们如果想要使用自定义的字段,则要在模型里面覆盖 CREATED_AT、UPDATED_AT 这两个常量(下面有定义)
* 其他:
* 默认使用 mysql 的 datetime 类型,如果需要更改为 10 位整型,可以设置 protected $dateFormat = 'U'; ()
*/
public $timestamps = true;

/**
* 我们在给模型对象设置非 public 属性的时候,会通过 setAttributes 方法,保存到该数组中
* usage:
* $user = new User();
* $user->name = 'laravel';
* User 中没有定义 public $name 的时候, $attributes 就会多了 'name' => 'laravel' 的键值对
*/
protected $attributes = [];

/**
* 保存模型的原始数据,后续修改模型属性只会修改 $attributes,以便侦测变化
*/
protected $original = [];

/**
* 模型的关联数据
*/
protected $relations = [];

/**
* 隐藏的属性,我们调用模型的 toArray 方法的时候不会得到该数组中的属性,
* 如果需要也得到隐藏属性,可以通过 withHidden 方法
*/
protected $hidden = [];

/**
* 与 hidden 数组作用差不多,共同作用
*/
protected $visible = [];

/**
* 其中一个用法,根据现有某几个属性,计算出新属性,并在 模型 toArray 的时候显示
* usage:
* 模型里面定义: protected $appends = ['full_name'];
* public function getFullNameAttribute() { return $this->firstName . ' ' . $this->lastName; }
*/
protected $appends = [];

/**
* mass assignment 的时候可以批量设置的属性,目的是防止用户提交我们不想更新的字段
* 注意:
* 和 $guarded 同时使用的时候, $guard 设置的会无效
*/
protected $fillable = [];

/**
* 不能批量赋值的属性
*/
protected $guarded = ['*'];

/**
* 需要进行时间格式转换的字段
* 应用场景:
* 一般情况我们只定义了 created_at、updated_at,我们还可能会保存用户注册时间这些,register_time,
* 这样我们就可以定义,protected $dates = ['register_time'];
* 好比如:
* 我们定义的 $dateFormat 为 mysql 的 datetime 格式,我们即使把 register_time 设置为 time(),
* 实际保存的其实是 datetime 格式的
*/
protected $dates = [];

/**
* created_at、updated_at、$dates数组 进行时间格式转换的时候使用的格式
*/
protected $dateFormat;

/**
* 自动格式转换,定义方式: protected $casts = ['info' => 'json'];
* 所有可用格式: int、integer、real、float、double、string、bool、boolean、
* object、array、json、collection、date、datetime
* 应用场景:
* 我们想要保存某些特殊格式到数据库(如json、object),我们可以使用该数组对我们的数据进行自动转换,
* usage:
* $user = User::create([
* 'name' => 'ruby',
* 'info' => ['city' => 'Guangzhou']
* ]);
*
* $query_user = User::find($user['id']);
* dd($query_user->info);
* 这里我们可以看数据库保存的 info 字段,实际上是 json 编码的,并且取出来的是 json 解码后的数据
*/
protected $casts = [];

/**
* 需要同步更新 updated_at 的关联,调用 save 方法的时候会更新该数组里面定义的关联的 updated_at 字段
*/
protected $touches = [];

/**
* todo 自定义事件,目前还没用过 -_-
*/
protected $observables = [];

/**
* 需要预加载的关联
*/
protected $with = [];

/**
* The class name to be used in polymorphic relations.
*
* todo 也不知道
*/
protected $morphClass;

/**
* 模型是否存在
*/
public $exists = false;

/**
* 判断模型是否是当前请求插入的
*/
public $wasRecentlyCreated = false;

/**
* 模型属性名是否是下划线形式的
*/
public static $snakeAttributes = true;

/**
* 用来建立数据库连接
*
* @var \Illuminate\Database\ConnectionResolverInterface
*/
protected static $resolver;

/**
* 用来分发模型事件
*
* @var \Illuminate\Contracts\Events\Dispatcher
*/
protected static $dispatcher;

/**
* 模型 new 的时候调用模型的 bootXXX 方法, XXX 是模型名称
*/
protected static $booted = [];

/**
* 全局查询条件,需要定义
*
* @see \Illuminate\Database\Eloquent\ScopeInterface
*/
protected static $globalScopes = [];

/**
* 批量设置属性的时候是否不需要筛选字段
*/
protected static $unguarded = false;

/**
* 缓存 getXXAttribute 的值
*/
protected static $mutatorCache = [];

/**
* 多对多关联方法,不知道哪里用了
*/
public static $manyMethods = ['belongsToMany', 'morphToMany', 'morphedByMany'];

/**
* 创建时间戳字段名称
*/
const CREATED_AT = 'created_at';

/**
* 更新时间戳字段名称
*/
const UPDATED_AT = 'updated_at';
}

模型定义

App\User

1
2
3
4
5
6
7
class User
{
public function customer()
{
return $this->hasOne('App\Customer');
}
}

App\Customer

1
2
3
4
5
6
7
class Customer
{
public function user()
{
return $this->belongsTo('App\User');
}
}

需要注意的是 associate 方法是 BelongsTo 类才有,所以正确的调用方法如下:

1
2
3
4
5
6
7
8
use App\User;
use App\Customer;

$user = new User($data);
$customer = new Customer($customerData);

$customer->user()->associate($user);
$customer->save();

与此相反的方法是 disassociate 方法:取消两个模型之间的 belongsTo 关联

1
2
$customer->user()->disassociate();
$customer->save();

此方法需要注意的是,disassociate 并不会删除记录,只是更新关联的字段为 null。上面这种操作会把 customer 表的 user_id 设置为 null

附(通过关联的模型保存):

1
2
3
4
5
6
7
8
use App\User;
use App\Customer;

$user = new User($data);
$user->save();

$customer = new Customer($customerData);
$user->customer()->save($customer);

用户模型 App\User

标签模型 App\Tag

中间表 user_tag (user_id, tag_id)

在user模型中定义tags关联如下:

1
2
3
4
5
6
7
class User extend Model
{
public function tags()
{
return $this->belongsToMany('App\Tag', 'user_tag');
}
}

上面的 belongsToMany 方法中的第二个参数 user_tag 是中间表,保存了 user_idtag_id。 其中 user_id 关联 usersid, tag_id 关联 tagsid