企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
[TOC] # 例子1 顾名思义,这描述的是两个模型之间一对一的关系。这种关系是不需要中间表的。 假如我们有两个模型:User 和 Account,分别对应注册用户和消费者,他们是一对一的关系,那么如果我们要使用 Eloquent 提供的一对一关系方法,表结构应该是这样的: ~~~ user: id ... ... account_id account: id ... ... user_id ~~~ 假设我们需要在 User 模型中查询对应的 Account 表的信息,那么代码应该是这样的。 `/app/models/User.php`: ~~~ class User extends Eloquent { protected $table = 'users'; public function hasOneAccount() { return $this->hasOne('Account', 'user_id', 'id'); } } ~~~ 然后,当我们需要用到这种关系的时候,该如何使用呢?如下: `$account = User::find(10)->hasOneAccount;` 此时得到的 `$account` 即为 `Account` 类的一个实例。 这里最难的地方在于后面的两个 foreign_key 和 local_key 的设置,大家可以就此记住:在 User 类中,无论 hasOne 谁,第二个参数都是 `user_id`,第三个参数一般都是 `id`。由于前面的 `find(10)` 已经锁定了 id = 10,所以这段函数对应的 SQL 为: `select * from account where user_id=10`。 这段代码除了展示了一对一关系该如何使用之外,还传达了三点信息,也是我对于大家使用 Eloquent 时候的建议: 每一个 Model 中都指定表名 has one account 这样的关系写成 `hasOneAccount()` 而不是简单的 `account()` 每次使用模型间关系的时候都写全参数,不要省略 相应的 ~~~ class Account extends Eloquent { protected $table = 'accounts'; public function belongsToUser() { return $this->belongsTo('User', 'user_id', 'id'); } } ~~~ ## 总结 **查询** ~~~ $res = User::find(2)->hasOneAccount(); dd($res->get()->toArray()); ~~~ **新增** ~~~ $account->name = "xjd"; $res = User::find(3)->hasOneAccount()->save($account); //显示的是account表新增的 dd($res->toArray()); ~~~ 2个都新建 ~~~ $uObj = $user->create([ 'name' => 'u的name', ]); $account = new Account(['name' => 'A的name']); $res = $uObj->hasOneAccount()->save($account); //返回account的对象 dd($res); ~~~ **删除** ~~~ $res = User::find(3)->hasOneAccount()->delete(); //返回修改的条目,user中的不会删除 dd($res); ~~~ **更改** ~~~ //获取到关联的消息 $userObj = User::find(3); $account = $userObj->hasOneAccount(); //改的是account表 $res = $account->update(['name' => "account的name修改"]); //返回修改的条目 dd($res); ~~~ # 例子2 每个用户有一个头像,存放于avatars表中 **users 表** | 键名 | 类型 | | --- | --- | | id | PK | | username | varchar(100) | | password | varchar(100) | | created_at | timestamp | | updated_at | timestamp | **avatars 表** | 键名 | 类型 | | --- | --- | | id | PK | | uid | FK users's id | | path | varchar(200) | | created_at | timestamp | | updated_at | timestamp | ## 实现 User.php ~~~ function avatar() { //参数分别为 model, foreign_key, local_key return $this->hasOne('App\\Avatar', 'uid', 'id'); } ~~~ Avatar.php ~~~ function user() { //后两个参数与User中的参数顺序相反 return $this->belongsTo('App\\User', 'id', 'uid'); } ~~~ ## 操作 `$user = User::find(1);` ### 查 `echo $user->avatar->path;` ~~~ //上面语句可能会报错,因为没有校验avatar是否存在 $avatar = $user->avatar; echo !empty($avatar) ? $avatar->path : ''; ~~~ ### 新建 **create开启白名单或者指定黑名单** ~~~ $user->avatar()->create(['path' => 'attachments/1.jpg']); 或者 $avatar = Avatar::create([ 'uid' => $user->getKey(), 'path' => 'attachments/1.jpg', ]); 或者 $avatar = new Avatar(['path' => 'attachments/1.jpg']) $user->avatar()->save($avatar) ~~~ **上面的这些新建方法可以新建与此user相关的无数条avatar,为了确保一条,需要创建前需先查询是否存在记录。(因为一对一、一对多关系本身的界线就很模糊)** ### 修改 `$user->avatar()->update(['path' => '/www/website/project_name/attachments/1.jpg']);` //如果有多条,则修改第一条(但是为什么会有多条,因为create太多了?) ### 删除 ~~~ $user->avatar()->delete(); //删除找到的第一条 ~~~ `$user`里面的不会删除,关联的表中的会被删除