本篇为您讲述ThinkPHP5.0的关联定义和基础用法,主要包括:
- - [基本定义](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/145257#u57FAu672Cu5B9Au4E49)
- [一对一关联](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/145257#u4E00u5BF9u4E00u5173u8054)
- [关联定义](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/145257#u5173u8054u5B9Au4E49)
- [关联写入](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/145257#u5173u8054u5199u5165)
- [关联查询](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/145257#u5173u8054u67E5u8BE2)
- [关联更新](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/145257#u5173u8054u66F4u65B0)
- [关联删除](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/145257#u5173u8054u5220u9664)
- [一对多关联](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/145257#u4E00u5BF9u591Au5173u8054)
- [关联定义](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/145257#u5173u8054u5B9Au4E49-1)
- [关联新增](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/145257#u5173u8054u65B0u589E)
- [关联查询](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/145257#u5173u8054u67E5u8BE2-1)
- [关联更新](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/145257#u5173u8054u66F4u65B0-1)
- [关联删除](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/145257#u5173u8054u5220u9664-1)
- [多对多关联](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/145257#u591Au5BF9u591Au5173u8054)
- [关联定义](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/145257#u5173u8054u5B9Au4E49-2)
- [关联新增](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/145257#u5173u8054u65B0u589E-1)
- [关联删除](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/145257#u5173u8054u5220u9664-2)
- [关联查询](http://ihavenolimitations.xyz/thinkphp/thinkphp5_quickstart/145257#u5173u8054u67E5u8BE2-2)
## 基本定义
`ThinkPHP5.0`的关联采用了对象化的操作模式,你无需继承不同的模型类,只是把关联定义成一个方法,并且直接通过当前模型对象的属性名获取定义的关联数据。
举个例子,有一个用户模型`User`,有一个关联的模型对象`Book`,每个用户有多本书,`User`模型定义如下:
```
<pre class="calibre18">
```
<span class="hljs-operator"><span class="hljs-number"><?php</span><span class="hljs-keyword">namespace</span> <span class="hljs-title">app</span>\<span class="hljs-title">index</span>\<span class="hljs-title">model</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">think</span>\<span class="hljs-title">Model</span>;
<span class="hljs-operator"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Model</span></span>{
<span class="hljs-comment">// 定义关联方法</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">books</span><span class="hljs-number">()</span></span>{
<span class="hljs-keyword">return</span> <span class="hljs-regexp">$this</span>->hasMany(<span class="hljs-string">'Book'</span>);
}
}</span>
```
```
> #### 提示:
>
> - - - - - -
>
> `User`模型的`books`方法就是一个关联定义方法,方法名可以随意命名,但注意要避免和`User`模型对象的字段属性冲突。
实际获取关联数据的时候,就是采用下面的方式:
```
<pre class="calibre18">
```
<span class="hljs-regexp">$user</span> = User::get(<span class="hljs-number">5</span>);
<span class="hljs-comment">// 获取User对象的nickname属性</span><span class="hljs-keyword">echo</span> <span class="hljs-regexp">$user</span>->nickname;
<span class="hljs-comment">// 获取User对象的Book关联对象</span>
dump(<span class="hljs-regexp">$user</span>->books);
<span class="hljs-comment">// 执行关联的Book对象的查询</span><span class="hljs-regexp">$user</span>->books()->where(<span class="hljs-string">'name'</span>,<span class="hljs-string">'thinkphp'</span>)->find();
```
```
对于涉及的代码用法,目前不用深究,后面会详细描述。
一般来说,关联关系包括:
- 一对一关联:`HAS_ONE` 以及相对的 `BELONGS_TO`
- 一对多关联:`HAS_MANY` 以及相对的 `BELONGS_TO`
- 多对多关联:`BELONGS_TO_MANY`
后面会详细讲解每一种关联的用法。
## 一对一关联
一对一关联是一种最简单的关联,例如每个用户都有一份档案,每个公司都有一个营业执照等等。
在这之前,我们先创建数据表如下:
```
<pre class="calibre18">
```
<span class="hljs-operator"><span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">IF</span> <span class="hljs-keyword">EXISTS</span> <span class="hljs-string">`think_user`</span>;</span>
<span class="hljs-operator"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">IF</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> <span class="hljs-string">`think_user`</span> (
<span class="hljs-string">`id`</span> <span class="hljs-number">int</span>(<span class="hljs-number">6</span>) <span class="hljs-keyword">UNSIGNED</span> <span class="hljs-keyword">NOT</span> <span class="hljs-number">NULL</span> AUTO_INCREMENT,
<span class="hljs-string">`nickname`</span> <span class="hljs-number">varchar</span>(<span class="hljs-number">25</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-number">NULL</span>,
<span class="hljs-string">`name`</span> <span class="hljs-number">varchar</span>(<span class="hljs-number">25</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-number">NULL</span>,
<span class="hljs-string">`password`</span> <span class="hljs-number">varchar</span>(<span class="hljs-number">50</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-number">NULL</span>,
<span class="hljs-string">`create_time`</span> <span class="hljs-number">int</span>(<span class="hljs-number">11</span>) <span class="hljs-keyword">UNSIGNED</span> <span class="hljs-keyword">NOT</span> <span class="hljs-number">NULL</span>,
<span class="hljs-string">`update_time`</span> <span class="hljs-number">int</span>(<span class="hljs-number">11</span>) <span class="hljs-keyword">UNSIGNED</span> <span class="hljs-keyword">NOT</span> <span class="hljs-number">NULL</span>,
<span class="hljs-string">`status`</span> tinyint(<span class="hljs-number">1</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-number">0</span>,
PRIMARY <span class="hljs-keyword">KEY</span> (<span class="hljs-string">`id`</span>)
) <span class="hljs-keyword">ENGINE</span>=MyISAM <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">CHARSET</span>=utf8;</span>
<span class="hljs-operator"><span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">IF</span> <span class="hljs-keyword">EXISTS</span> <span class="hljs-string">`think_profile`</span>;</span>
<span class="hljs-operator"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">IF</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> <span class="hljs-string">`think_profile`</span> (
<span class="hljs-string">`id`</span> <span class="hljs-number">int</span>(<span class="hljs-number">6</span>) <span class="hljs-keyword">UNSIGNED</span> <span class="hljs-keyword">NOT</span> <span class="hljs-number">NULL</span> AUTO_INCREMENT,
<span class="hljs-string">`truename`</span> <span class="hljs-number">varchar</span>(<span class="hljs-number">25</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-number">NULL</span>,
<span class="hljs-string">`birthday`</span> <span class="hljs-number">int</span>(<span class="hljs-number">11</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-number">NULL</span>,
<span class="hljs-string">`address`</span> <span class="hljs-number">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-number">NULL</span>,
<span class="hljs-string">`email`</span> <span class="hljs-number">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-number">NULL</span>,
<span class="hljs-string">`user_id`</span> <span class="hljs-number">int</span>(<span class="hljs-number">6</span>) <span class="hljs-keyword">UNSIGNED</span> <span class="hljs-keyword">NOT</span> <span class="hljs-number">NULL</span>,
PRIMARY <span class="hljs-keyword">KEY</span> (<span class="hljs-string">`id`</span>)
) <span class="hljs-keyword">ENGINE</span>=MyISAM <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">CHARSET</span>=utf8;</span>
```
```
### 关联定义
我们以用户和档案的一对一关联为例,在`User`模型类中添加关联定义方法,然后在方法中调用`hasOne`方法即可:
```
<pre class="calibre18">
```
<span class="hljs-operator"><span class="hljs-number"><?php</span><span class="hljs-keyword">namespace</span> <span class="hljs-title">app</span>\<span class="hljs-title">index</span>\<span class="hljs-title">model</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">think</span>\<span class="hljs-title">Model</span>;
<span class="hljs-operator"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Model</span></span>{
<span class="hljs-comment">// 开启自动写入时间戳</span><span class="hljs-keyword">protected</span> <span class="hljs-regexp">$autoWriteTimestamp</span> = <span class="hljs-keyword">true</span>;
<span class="hljs-comment">// 定义自动完成的属性</span><span class="hljs-keyword">protected</span> <span class="hljs-regexp">$insert</span> = [<span class="hljs-string">'status'</span> => <span class="hljs-number">1</span>];
<span class="hljs-comment">// 定义关联方法</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">profile</span><span class="hljs-number">()</span></span>{
<span class="hljs-comment">// 用户HAS ONE档案关联</span><span class="hljs-keyword">return</span> <span class="hljs-regexp">$this</span>->hasOne(<span class="hljs-string">'Profile'</span>);
}
}</span>
```
```
hasOne方法有5个参数,依次分别是:
> #### hasOne('关联模型名','关联外键','主键','别名定义','join类型')
默认的外键是:**当前模型名\_id**,主键则是自动获取,如果你的表设计符合这一规范的话,只需要设置关联的模型名即可.
通常关联模型和当前模型都是相同的命名空间,如果关联模型在不同的命名空间,需要指定完整的类名,例如:
```
<pre class="calibre18">
```
<span class="hljs-comment">// 关联admin模块下面的模型对象</span><span class="hljs-keyword">return</span> <span class="hljs-regexp">$this</span>->hasOne(<span class="hljs-string">'\app\admin\Profile'</span>);
```
```
在关联查询的时候,默认使用当前模型的名称(小写)作为数据表别名,可以指定查询使用的数据表别名,例如:
```
<pre class="calibre18">
```
<span class="hljs-comment">// 用户HAS ONE档案关联</span><span class="hljs-keyword">return</span> <span class="hljs-regexp">$this</span>->hasOne(<span class="hljs-string">'Profile'</span>,<span class="hljs-string">'user_id'</span>,<span class="hljs-string">'id'</span>,[<span class="hljs-string">'user'</span>=><span class="hljs-string">'member'</span>,<span class="hljs-string">'profile'</span>=><span class="hljs-string">'info'</span>]);
```
```
要进行模型的关联操作,我们必须同时定义好关联模型,`Profile`模型定义如下:
```
<pre class="calibre18">
```
<?php
namespace app\index\model;
use think\<span class="hljs-operator">Model</span>;
<span class="hljs-operator"><span class="hljs-keyword">class</span> <span class="hljs-title">Profile</span> <span class="hljs-keyword"><span class="hljs-operator">extends</span></span> <span class="hljs-title">Model</span></span>{
<span class="hljs-keyword">protected</span> $<span class="hljs-operator"><span class="hljs-keyword">type</span> =</span> [
<span class="hljs-operator">'birthda</span>y' => <span class="hljs-operator">'timestamp</span>:<span class="hljs-operator">Y</span>-m-d',
];
}
```
```
可以看到`Profile`模型中并没有定义关联方法。如果你的关联操作都是基于`User`模型的话,`Profile`模型中并不需要定义关联方法。
如果你需要基于`Profile`模型来进行关联操作,则需要在`Profile`模型中定义对应的`BELONGS_TO`关联,如下:
```
<pre class="calibre18">
```
<span class="hljs-operator"><span class="hljs-number"><?php</span><span class="hljs-keyword">namespace</span> <span class="hljs-title">app</span>\<span class="hljs-title">index</span>\<span class="hljs-title">model</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">think</span>\<span class="hljs-title">Model</span>;
<span class="hljs-operator"><span class="hljs-keyword">class</span> <span class="hljs-title">Profile</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Model</span></span>{
<span class="hljs-keyword">protected</span> <span class="hljs-regexp">$type</span> = [
<span class="hljs-string">'birthday'</span> => <span class="hljs-string">'timestamp:Y-m-d'</span>,
];
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">user</span><span class="hljs-number">()</span></span>{
<span class="hljs-comment">// 档案 BELONGS TO 关联用户</span><span class="hljs-keyword">return</span> <span class="hljs-regexp">$this</span>->belongsTo(<span class="hljs-string">'User'</span>);
}
}</span>
```
```
`belongsTo`方法和`hasOne`一样,也有5个参数:
> #### belongsTo('关联模型名','关联外键','关联模型主键','别名定义','join类型')
### 关联写入
首先来看下如何进行关联数据的写入,创建User控制器的add操作方法如下:
```
<pre class="calibre18">
```
<span class="hljs-operator"><span class="hljs-number"><?php</span><span class="hljs-keyword">namespace</span> <span class="hljs-title">app</span>\<span class="hljs-title">index</span>\<span class="hljs-title">controller</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">app</span>\<span class="hljs-title">index</span>\<span class="hljs-title">model</span>\<span class="hljs-title">Profile</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">app</span>\<span class="hljs-title">index</span>\<span class="hljs-title">model</span>\<span class="hljs-title">User</span> <span class="hljs-title">as</span> <span class="hljs-title">UserModel</span>;
<span class="hljs-operator"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span></span>{
<span class="hljs-comment">// 关联新增数据</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span><span class="hljs-number">()</span></span>{
<span class="hljs-regexp">$user</span> = <span class="hljs-keyword">new</span> UserModel;
<span class="hljs-regexp">$user</span>->name = <span class="hljs-string">'thinkphp'</span>;
<span class="hljs-regexp">$user</span>->password = <span class="hljs-string">'123456'</span>;
<span class="hljs-regexp">$user</span>->nickname = <span class="hljs-string">'流年'</span>;
<span class="hljs-keyword">if</span> (<span class="hljs-regexp">$user</span>->save()) {
<span class="hljs-comment">// 写入关联数据</span><span class="hljs-regexp">$profile</span> = <span class="hljs-keyword">new</span> Profile;
<span class="hljs-regexp">$profile</span>->truename = <span class="hljs-string">'刘晨'</span>;
<span class="hljs-regexp">$profile</span>->birthday = <span class="hljs-string">'1977-03-05'</span>;
<span class="hljs-regexp">$profile</span>->address = <span class="hljs-string">'中国上海'</span>;
<span class="hljs-regexp">$profile</span>->email = <span class="hljs-string">'thinkphp@qq.com'</span>;
<span class="hljs-regexp">$user</span>->profile()->save(<span class="hljs-regexp">$profile</span>);
<span class="hljs-keyword">return</span> <span class="hljs-string">'用户新增成功'</span>;
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">return</span> <span class="hljs-regexp">$user</span>->getError();
}
}
}</span>
```
```
关联模型的写入调用了关联方法`profile()`,该方法返回的是一个`Relation`对象,执行`save`方法会自动传入当前模型`User`的主键作为关联键值,所以不需要手动传入`Profile`模型的`user_id`属性。
`save`方法也可以直接使用数组而不是`Profile`对象,例如:
```
<pre class="calibre18">
```
<span class="hljs-operator"><span class="hljs-number"><?php</span><span class="hljs-keyword">namespace</span> <span class="hljs-title">app</span>\<span class="hljs-title">index</span>\<span class="hljs-title">controller</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">app</span>\<span class="hljs-title">index</span>\<span class="hljs-title">model</span>\<span class="hljs-title">Profile</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">app</span>\<span class="hljs-title">index</span>\<span class="hljs-title">model</span>\<span class="hljs-title">User</span> <span class="hljs-title">as</span> <span class="hljs-title">UserModel</span>;
<span class="hljs-operator"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Controller</span></span>{
<span class="hljs-comment">// 关联新增数据</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span><span class="hljs-number">()</span></span>{
<span class="hljs-regexp">$user</span> = <span class="hljs-keyword">new</span> UserModel;
<span class="hljs-regexp">$user</span>->name = <span class="hljs-string">'thinkphp'</span>;
<span class="hljs-regexp">$user</span>->password = <span class="hljs-string">'123456'</span>;
<span class="hljs-regexp">$user</span>->nickname = <span class="hljs-string">'流年'</span>;
<span class="hljs-keyword">if</span> (<span class="hljs-regexp">$user</span>->save()) {
<span class="hljs-comment">// 写入关联数据</span><span class="hljs-regexp">$profile</span>[<span class="hljs-string">'truename'</span>] = <span class="hljs-string">'刘晨'</span>;
<span class="hljs-regexp">$profile</span>[<span class="hljs-string">'birthday'</span>] = <span class="hljs-string">'1977-03-05'</span>;
<span class="hljs-regexp">$profile</span>[<span class="hljs-string">'address'</span>] = <span class="hljs-string">'中国上海'</span>;
<span class="hljs-regexp">$profile</span>[<span class="hljs-string">'email'</span>] = <span class="hljs-string">'thinkphp@qq.com'</span>;
<span class="hljs-regexp">$user</span>->profile()->save(<span class="hljs-regexp">$profile</span>);
<span class="hljs-keyword">return</span> <span class="hljs-string">'用户[ '</span> . <span class="hljs-regexp">$user</span>->name . <span class="hljs-string">' ]新增成功'</span>;
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">return</span> <span class="hljs-regexp">$user</span>->getError();
}
}
}</span>
```
```
### 关联查询
一对一的关联查询很简单,直接把关联对象当成属性来用即可,例如:
```
<pre class="calibre18">
```
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">read</span><span class="hljs-number">(<span class="hljs-regexp">$id</span>)</span></span>{
<span class="hljs-regexp">$user</span> = UserModel::get(<span class="hljs-regexp">$id</span>);
<span class="hljs-keyword">echo</span> <span class="hljs-regexp">$user</span>->name . <span class="hljs-string">'<br/>'</span>;
<span class="hljs-keyword">echo</span> <span class="hljs-regexp">$user</span>->nickname . <span class="hljs-string">'<br/>'</span>;
<span class="hljs-keyword">echo</span> <span class="hljs-regexp">$user</span>->profile->truename . <span class="hljs-string">'<br/>'</span>;
<span class="hljs-keyword">echo</span> <span class="hljs-regexp">$user</span>->profile->email . <span class="hljs-string">'<br/>'</span>;
}
```
```
访问URL地址:
```
<pre class="calibre18">
```
<span class="hljs-string">http:</span>
<span class="hljs-comment">//tp5.com/user/1</span>
```
```
最后输出结果为:
```
<pre class="calibre18">
```
<span class="hljs-title">thinkphp</span>
流年
刘晨
thinkphp<span class="hljs-regexp">@qq</span>.com
```
```
以上关联查询的时候,只有在获取关联对象(`$user->profile`)的时候才会进行实际的关联查询,缺点是会可能进行多次查询,但可以使用预载入查询来提高查询性能,对于一对一关联来说,只需要进行一次查询即可获取关联对象数据,例如:
```
<pre class="calibre18">
```
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">read</span><span class="hljs-number">(<span class="hljs-regexp">$id</span>)</span></span>{
<span class="hljs-regexp">$user</span> = UserModel::get(<span class="hljs-regexp">$id</span>,<span class="hljs-string">'profile'</span>);
<span class="hljs-keyword">echo</span> <span class="hljs-regexp">$user</span>->name . <span class="hljs-string">'<br/>'</span>;
<span class="hljs-keyword">echo</span> <span class="hljs-regexp">$user</span>->nickname . <span class="hljs-string">'<br/>'</span>;
<span class="hljs-keyword">echo</span> <span class="hljs-regexp">$user</span>->profile->truename . <span class="hljs-string">'<br/>'</span>;
<span class="hljs-keyword">echo</span> <span class="hljs-regexp">$user</span>->profile->email . <span class="hljs-string">'<br/>'</span>;
}
```
```
get方法使用第二个参数就表示进行关联预载入查询。
### 关联更新
一对一的关联更新如下:
```
<pre class="calibre18">
```
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">update</span><span class="hljs-number">(<span class="hljs-regexp">$id</span>)</span></span>{
<span class="hljs-regexp">$user</span> = UserModel::get(<span class="hljs-regexp">$id</span>);
<span class="hljs-regexp">$user</span>->name = <span class="hljs-string">'framework'</span>;
<span class="hljs-keyword">if</span> (<span class="hljs-regexp">$user</span>->save()) {
<span class="hljs-comment">// 更新关联数据</span><span class="hljs-regexp">$user</span>->profile->email = <span class="hljs-string">'liu21st@gmail.com'</span>;
<span class="hljs-regexp">$user</span>->profile->save();
<span class="hljs-keyword">return</span> <span class="hljs-string">'用户[ '</span> . <span class="hljs-regexp">$user</span>->name . <span class="hljs-string">' ]更新成功'</span>;
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">return</span> <span class="hljs-regexp">$user</span>->getError();
}
}
```
```
访问URL地址:
```
<pre class="calibre18">
```
<span class="hljs-string">http:</span>
<span class="hljs-comment">//tp5.com/user/update/1</span>
```
```
最后输出结果为:
```
<pre class="calibre18">
```
用户更新成
```
```
### 关联删除
关联删除代码如下:
```
<pre class="calibre18">
```
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">delete</span><span class="hljs-number">(<span class="hljs-regexp">$id</span>)</span></span>{
<span class="hljs-regexp">$user</span> = UserModel::get(<span class="hljs-regexp">$id</span>);
<span class="hljs-keyword">if</span> (<span class="hljs-regexp">$user</span>->delete()) {
<span class="hljs-comment">// 删除关联数据</span><span class="hljs-regexp">$user</span>->profile->delete();
<span class="hljs-keyword">return</span> <span class="hljs-string">'用户[ '</span> . <span class="hljs-regexp">$user</span>->name . <span class="hljs-string">' ]删除成功'</span>;
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">return</span> <span class="hljs-regexp">$user</span>->getError();
}
}
```
```
访问URL地址:
```
<pre class="calibre18">
```
<span class="hljs-string">http:</span>
<span class="hljs-comment">//tp5.com/user/delete/1</span>
```
```
页面输出结果为:
```
<pre class="calibre18">
```
用户删除成功
```
```
## 一对多关联
每个作者写有多本书就是一个典型的一对多关联,首先创建如下数据表:
```
<pre class="calibre18">
```
<span class="hljs-operator"><span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">IF</span> <span class="hljs-keyword">EXISTS</span> <span class="hljs-string">`think_book`</span>;</span>
<span class="hljs-operator"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">IF</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> <span class="hljs-string">`think_book`</span> (
<span class="hljs-string">`id`</span> <span class="hljs-number">int</span>(<span class="hljs-number">8</span>) <span class="hljs-keyword">UNSIGNED</span> <span class="hljs-keyword">NOT</span> <span class="hljs-number">NULL</span> AUTO_INCREMENT,
<span class="hljs-string">`title`</span> <span class="hljs-number">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-number">NULL</span>,
<span class="hljs-string">`publish_time`</span> <span class="hljs-number">int</span>(<span class="hljs-number">11</span>) <span class="hljs-keyword">UNSIGNED</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-number">NULL</span>,
<span class="hljs-string">`create_time`</span> <span class="hljs-number">int</span>(<span class="hljs-number">11</span>) <span class="hljs-keyword">UNSIGNED</span> <span class="hljs-keyword">NOT</span> <span class="hljs-number">NULL</span>,
<span class="hljs-string">`update_time`</span> <span class="hljs-number">int</span>(<span class="hljs-number">11</span>) <span class="hljs-keyword">UNSIGNED</span> <span class="hljs-keyword">NOT</span> <span class="hljs-number">NULL</span>,
<span class="hljs-string">`status`</span> tinyint(<span class="hljs-number">1</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-number">NULL</span>,
<span class="hljs-string">`user_id`</span> <span class="hljs-number">int</span>(<span class="hljs-number">6</span>) <span class="hljs-keyword">UNSIGNED</span> <span class="hljs-keyword">NOT</span> <span class="hljs-number">NULL</span>,
PRIMARY <span class="hljs-keyword">KEY</span> (<span class="hljs-string">`id`</span>)
) <span class="hljs-keyword">ENGINE</span>=MyISAM <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">CHARSET</span>=utf8;</span>
```
```
### 关联定义
在`User`模型类添加`Book`关联如下:
```
<pre class="calibre18">
```
<span class="hljs-operator"><span class="hljs-number"><?php</span><span class="hljs-keyword">namespace</span> <span class="hljs-title">app</span>\<span class="hljs-title">index</span>\<span class="hljs-title">model</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">think</span>\<span class="hljs-title">Model</span>;
<span class="hljs-operator"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Model</span></span>{
<span class="hljs-comment">// 开启自动写入时间戳</span><span class="hljs-keyword">protected</span> <span class="hljs-regexp">$autoWriteTimestamp</span> = <span class="hljs-keyword">true</span>;
<span class="hljs-comment">// 定义自动完成的属性</span><span class="hljs-keyword">protected</span> <span class="hljs-regexp">$insert</span> = [<span class="hljs-string">'status'</span> => <span class="hljs-number">1</span>];
<span class="hljs-comment">// 定义关联方法</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">profile</span><span class="hljs-number">()</span></span>{
<span class="hljs-keyword">return</span> <span class="hljs-regexp">$this</span>->hasOne(<span class="hljs-string">'Profile'</span>);
}
<span class="hljs-comment">// 定义关联</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">books</span><span class="hljs-number">()</span></span>{
<span class="hljs-keyword">return</span> <span class="hljs-regexp">$this</span>->hasMany(<span class="hljs-string">'Book'</span>);
}
}</span>
```
```
`hasMany`的参数如下:
> #### hasMany('关联模型名','关联外键','关联模型主键','别名定义')
`Book`模型类定义如下:
```
<pre class="calibre18">
```
<?php
namespace app\index\model;
use think\<span class="hljs-operator">Model</span>;
<span class="hljs-operator"><span class="hljs-keyword">class</span> <span class="hljs-title">Book</span> <span class="hljs-keyword"><span class="hljs-operator">extends</span></span> <span class="hljs-title">Model</span></span>{
<span class="hljs-keyword">protected</span> $<span class="hljs-operator"><span class="hljs-keyword">type</span> =</span> [
<span class="hljs-operator">'publish_tim</span>e' => <span class="hljs-operator">'timestamp</span>:<span class="hljs-operator">Y</span>-m-d',
];
<span class="hljs-comment">// 开启自动写入时间戳</span><span class="hljs-keyword">protected</span> $autoWriteTimestamp = <span class="hljs-number">true</span>;
<span class="hljs-comment">// 定义自动完成的属性</span><span class="hljs-keyword">protected</span> $insert = [<span class="hljs-operator">'statu</span>s' => <span class="hljs-number">1</span>];
}
```
```
如果需要定义对应的关联,则可以使用`belongsTo`方法:
```
<pre class="calibre18">
```
<span class="hljs-operator"><span class="hljs-number"><?php</span><span class="hljs-keyword">namespace</span> <span class="hljs-title">app</span>\<span class="hljs-title">index</span>\<span class="hljs-title">model</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">think</span>\<span class="hljs-title">Model</span>;
<span class="hljs-operator"><span class="hljs-keyword">class</span> <span class="hljs-title">Book</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Model</span></span>{
<span class="hljs-keyword">protected</span> <span class="hljs-regexp">$type</span> = [
<span class="hljs-string">'publish_time'</span> => <span class="hljs-string">'timestamp:Y-m-d'</span>,
];
<span class="hljs-comment">// 开启自动写入时间戳</span><span class="hljs-keyword">protected</span> <span class="hljs-regexp">$autoWriteTimestamp</span> = <span class="hljs-keyword">true</span>;
<span class="hljs-comment">// 定义自动完成的属性</span><span class="hljs-keyword">protected</span> <span class="hljs-regexp">$insert</span> = [<span class="hljs-string">'status'</span> => <span class="hljs-number">1</span>];
<span class="hljs-comment">// 定义关联方法</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">user</span><span class="hljs-number">()</span></span>{
<span class="hljs-keyword">return</span> <span class="hljs-regexp">$this</span>->belongsTo(<span class="hljs-string">'User'</span>);
}
}</span>
```
```
### 关联新增
添加`addBook`方法用于新增关联数据:
```
<pre class="calibre18">
```
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addBook</span><span class="hljs-number">()</span></span>{
<span class="hljs-regexp">$user</span> = UserModel::get(<span class="hljs-number">1</span>);
<span class="hljs-regexp">$book</span> = <span class="hljs-keyword">new</span> Book;
<span class="hljs-regexp">$book</span>->title = <span class="hljs-string">'ThinkPHP5快速入门'</span>;
<span class="hljs-regexp">$book</span>->publish_time = <span class="hljs-string">'2016-05-06'</span>;
<span class="hljs-regexp">$user</span>->books()->save(<span class="hljs-regexp">$book</span>);
<span class="hljs-keyword">return</span> <span class="hljs-string">'添加Book成功'</span>;
}
```
```
对于一对多关联,也可以批量增加数据:
```
<pre class="calibre18">
```
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addBook</span><span class="hljs-number">()</span></span>{
<span class="hljs-regexp">$user</span> = UserModel::get(<span class="hljs-number">1</span>);
<span class="hljs-regexp">$books</span> = [
[<span class="hljs-string">'title'</span> => <span class="hljs-string">'ThinkPHP5快速入门'</span>, <span class="hljs-string">'publish_time'</span> => <span class="hljs-string">'2016-05-06'</span>],
[<span class="hljs-string">'title'</span> => <span class="hljs-string">'ThinkPHP5开发手册'</span>, <span class="hljs-string">'publish_time'</span> => <span class="hljs-string">'2016-03-06'</span>],
];
<span class="hljs-regexp">$user</span>->books()->saveAll(<span class="hljs-regexp">$books</span>);
<span class="hljs-keyword">return</span> <span class="hljs-string">'添加Book成功'</span>;
}
```
```
### 关联查询
可以直接调用模型的属性获取全部关联数据,例如:
```
<pre class="calibre18">
```
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">read</span><span class="hljs-number">()</span></span>{
<span class="hljs-regexp">$user</span> = UserModel::get(<span class="hljs-number">1</span>);
<span class="hljs-regexp">$books</span> = <span class="hljs-regexp">$user</span>->books;
dump(<span class="hljs-regexp">$books</span>);
}
```
```
一对多查询同样可以使用预载入查询,例如:
```
<pre class="calibre18">
```
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">read</span><span class="hljs-number">()</span></span>{
<span class="hljs-regexp">$user</span> = UserModel::get(<span class="hljs-number">1</span>,<span class="hljs-string">'books'</span>);
<span class="hljs-regexp">$books</span> = <span class="hljs-regexp">$user</span>->books;
dump(<span class="hljs-regexp">$books</span>);
}
```
```
一对多预载入查询会在原先延迟查询的基础上增加一次查询,可以解决典型的`N+1`次查询问题。
如果要过滤查询,可以调用关联方法:
```
<pre class="calibre18">
```
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">read</span><span class="hljs-number">()</span></span>{
<span class="hljs-regexp">$user</span> = UserModel::get(<span class="hljs-number">1</span>);
<span class="hljs-comment">// 获取状态为1的关联数据</span><span class="hljs-regexp">$books</span> = <span class="hljs-regexp">$user</span>->books()->where(<span class="hljs-string">'status'</span>,<span class="hljs-number">1</span>)->select();
dump(<span class="hljs-regexp">$books</span>);
<span class="hljs-comment">// 获取作者写的某本书</span><span class="hljs-regexp">$book</span> = <span class="hljs-regexp">$user</span>->books()->getByTitle(<span class="hljs-string">'ThinkPHP5快速入门'</span>);
dump(<span class="hljs-regexp">$book</span>);
}
```
```
还可以根据关联数据来查询当前模型数据,例如:
```
<pre class="calibre18">
```
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">read</span><span class="hljs-number">()</span></span>{
<span class="hljs-comment">// 查询有写过书的作者列表</span><span class="hljs-regexp">$user</span> = UserModel::has(<span class="hljs-string">'books'</span>)->select();
<span class="hljs-comment">// 查询写过三本书以上的作者</span><span class="hljs-regexp">$user</span> = UserModel::has(<span class="hljs-string">'books'</span>, <span class="hljs-string">'>='</span>, <span class="hljs-number">3</span>)->select();
<span class="hljs-comment">// 查询写过ThinkPHP5快速入门的作者</span><span class="hljs-regexp">$user</span> = UserModel::hasWhere(<span class="hljs-string">'books'</span>, [<span class="hljs-string">'title'</span> => <span class="hljs-string">'ThinkPHP5快速入门'</span>])->select();
}
```
```
### 关联更新
下面来进行关联数据的更新
```
<pre class="calibre18">
```
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">update</span><span class="hljs-number">(<span class="hljs-regexp">$id</span>)</span></span>{
<span class="hljs-regexp">$user</span> = UserModel::get(<span class="hljs-regexp">$id</span>);
<span class="hljs-regexp">$book</span> = <span class="hljs-regexp">$user</span>->books()->getByTitle(<span class="hljs-string">'ThinkPHP5开发手册'</span>);
<span class="hljs-regexp">$book</span>->title = <span class="hljs-string">'ThinkPHP5快速入门'</span>;
<span class="hljs-regexp">$book</span>->save();
}
```
```
或者使用查询构建器的`update`方法进行更新(但可能无法触发关联模型的事件)。
```
<pre class="calibre18">
```
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">update</span><span class="hljs-number">(<span class="hljs-regexp">$id</span>)</span></span>{
<span class="hljs-regexp">$user</span> = UserModel::get(<span class="hljs-regexp">$id</span>);
<span class="hljs-regexp">$user</span>->books()->where(<span class="hljs-string">'title'</span>, <span class="hljs-string">'ThinkPHP5快速入门'</span>)->update([<span class="hljs-string">'title'</span> => <span class="hljs-string">'ThinkPHP5开发手册'</span>]);
}
```
```
### 关联删除
删除部分关联数据:
```
<pre class="calibre18">
```
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">delete</span><span class="hljs-number">(<span class="hljs-regexp">$id</span>)</span></span>{
<span class="hljs-regexp">$user</span> = UserModel::get(<span class="hljs-regexp">$id</span>);
<span class="hljs-comment">// 删除部分关联数据</span><span class="hljs-regexp">$book</span> = <span class="hljs-regexp">$user</span>->books()->getByTitle(<span class="hljs-string">'ThinkPHP5开发手册'</span>);
<span class="hljs-regexp">$book</span>->delete();
}
```
```
删除所有的关联数据:
```
<pre class="calibre18">
```
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">delete</span><span class="hljs-number">(<span class="hljs-regexp">$id</span>)</span></span>{
<span class="hljs-regexp">$user</span> = UserModel::get(<span class="hljs-regexp">$id</span>);
<span class="hljs-keyword">if</span>(<span class="hljs-regexp">$user</span>->delete()){
<span class="hljs-comment">// 删除所有的关联数据</span><span class="hljs-regexp">$user</span>->books()->delete();
}
}
```
```
## 多对多关联
一个用户会有多个角色,同时一个角色也会包含多个用户,这就是一个典型的多对多关联,先创建一个角色表`think_role`结构如下:
```
<pre class="calibre18">
```
<span class="hljs-operator"><span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">IF</span> <span class="hljs-keyword">EXISTS</span> <span class="hljs-string">`think_role`</span>;</span>
<span class="hljs-operator"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">IF</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> <span class="hljs-string">`think_role`</span> (
<span class="hljs-string">`id`</span> <span class="hljs-number">int</span>(<span class="hljs-number">5</span>) <span class="hljs-keyword">UNSIGNED</span> <span class="hljs-keyword">NOT</span> <span class="hljs-number">NULL</span> AUTO_INCREMENT,
<span class="hljs-string">`name`</span> <span class="hljs-number">varchar</span>(<span class="hljs-number">25</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-number">NULL</span>,
<span class="hljs-string">`title`</span> <span class="hljs-number">varchar</span>(<span class="hljs-number">50</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-number">NULL</span>,
PRIMARY <span class="hljs-keyword">KEY</span> (<span class="hljs-string">`id`</span>)
) <span class="hljs-keyword">ENGINE</span>=MyISAM <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">CHARSET</span>=utf8;</span>
```
```
多对多关联通常一定会有一个中间表,也称为枢纽表,所以需要创建一个用户角色的中间表,这里创建了一个`think_access`表,结构如下:
```
<pre class="calibre18">
```
<span class="hljs-operator"><span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">IF</span> <span class="hljs-keyword">EXISTS</span> <span class="hljs-string">`think_access`</span>;</span>
<span class="hljs-operator"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">IF</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> <span class="hljs-string">`think_access`</span> (
<span class="hljs-string">`user_id`</span> <span class="hljs-number">int</span>(<span class="hljs-number">6</span>) <span class="hljs-keyword">UNSIGNED</span> <span class="hljs-keyword">NOT</span> <span class="hljs-number">NULL</span>,
<span class="hljs-string">`role_id`</span> <span class="hljs-number">int</span>(<span class="hljs-number">5</span>) <span class="hljs-keyword">UNSIGNED</span> <span class="hljs-keyword">NOT</span> <span class="hljs-number">NULL</span>
) <span class="hljs-keyword">ENGINE</span>=MyISAM <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">CHARSET</span>=utf8;</span>
```
```
### 关联定义
给User模型添加多对多关联方法定义
```
<pre class="calibre18">
```
<span class="hljs-operator"><span class="hljs-number"><?php</span><span class="hljs-keyword">namespace</span> <span class="hljs-title">app</span>\<span class="hljs-title">index</span>\<span class="hljs-title">model</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">think</span>\<span class="hljs-title">Model</span>;
<span class="hljs-operator"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Model</span></span>{
<span class="hljs-comment">// 开启自动写入时间戳</span><span class="hljs-keyword">protected</span> <span class="hljs-regexp">$autoWriteTimestamp</span> = <span class="hljs-keyword">true</span>;
<span class="hljs-comment">// 定义自动完成的属性</span><span class="hljs-keyword">protected</span> <span class="hljs-regexp">$insert</span> = [<span class="hljs-string">'status'</span> => <span class="hljs-number">1</span>];
<span class="hljs-comment">// 定义一对一关联</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">profile</span><span class="hljs-number">()</span></span>{
<span class="hljs-keyword">return</span> <span class="hljs-regexp">$this</span>->hasOne(<span class="hljs-string">'Profile'</span>);
}
<span class="hljs-comment">// 定义一对多关联</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">books</span><span class="hljs-number">()</span></span>{
<span class="hljs-keyword">return</span> <span class="hljs-regexp">$this</span>->hasMany(<span class="hljs-string">'Book'</span>);
}
<span class="hljs-comment">// 定义多对多关联</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">roles</span><span class="hljs-number">()</span></span>{
<span class="hljs-comment">// 用户 BELONGS_TO_MANY 角色</span><span class="hljs-keyword">return</span> <span class="hljs-regexp">$this</span>->belongsToMany(<span class="hljs-string">'Role'</span>, <span class="hljs-string">'think_access'</span>);
}
}</span>
```
```
`belongsToMany`的参数如下:
> #### belongsToMany('关联模型名','中间表名称','关联外键','关联模型主键','别名定义')
`Role`模型定义如下:
```
<pre class="calibre18">
```
<span class="hljs-operator"><span class="hljs-number"><?php</span><span class="hljs-keyword">namespace</span> <span class="hljs-title">app</span>\<span class="hljs-title">index</span>\<span class="hljs-title">model</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">think</span>\<span class="hljs-title">Model</span>;
<span class="hljs-operator"><span class="hljs-keyword">class</span> <span class="hljs-title">Role</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Model</span></span>{
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">user</span><span class="hljs-number">()</span></span>{
<span class="hljs-comment">// 角色 BELONGS_TO_MANY 用户</span><span class="hljs-keyword">return</span> <span class="hljs-regexp">$this</span>->belongsToMany(<span class="hljs-string">'User'</span>, <span class="hljs-string">'think_access'</span>);
}
}</span>
```
```
对于枢纽表并不需要创建模型类,在多对多关联关系中,并不需要直接操作枢纽表。
### 关联新增
给某个用户增加编辑角色,并且由于这个角色还没创建过,所以可以使用下面的方式:
```
<pre class="calibre18">
```
<span class="hljs-comment">// 关联新增数据</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span><span class="hljs-number">()</span></span>{
<span class="hljs-regexp">$user</span> = UserModel::getByNickname(<span class="hljs-string">'张三'</span>);
<span class="hljs-comment">// 新增用户角色 并自动写入枢纽表</span><span class="hljs-regexp">$user</span>->roles()->save([<span class="hljs-string">'name'</span> => <span class="hljs-string">'editor'</span>, <span class="hljs-string">'title'</span> => <span class="hljs-string">'编辑'</span>]);
<span class="hljs-keyword">return</span> <span class="hljs-string">'用户角色新增成功'</span>;
}
```
```
也可以批量新增用户的角色如下:
```
<pre class="calibre18">
```
<span class="hljs-comment">// 关联新增数据</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span><span class="hljs-number">()</span></span>{
<span class="hljs-regexp">$user</span> = UserModel::getByNickname(<span class="hljs-string">'张三'</span>);
<span class="hljs-comment">// 给当前用户新增多个用户角色</span><span class="hljs-regexp">$user</span>->roles()->saveAll([
[<span class="hljs-string">'name'</span> => <span class="hljs-string">'leader'</span>, <span class="hljs-string">'title'</span> => <span class="hljs-string">'领导'</span>],
[<span class="hljs-string">'name'</span> => <span class="hljs-string">'admin'</span>, <span class="hljs-string">'title'</span> => <span class="hljs-string">'管理员'</span>],
]);
<span class="hljs-keyword">return</span> <span class="hljs-string">'用户角色新增成功'</span>;
}
```
```
现在给另外一个用户增加编辑角色,由于该角色已经存在了,所以只需要使用`attach`方法增加枢纽表的关联数据:
```
<pre class="calibre18">
```
<span class="hljs-comment">// 关联新增数据</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span><span class="hljs-number">()</span></span>{
<span class="hljs-regexp">$user</span> = UserModel::getByNickname(<span class="hljs-string">'张三'</span>);
<span class="hljs-regexp">$role</span> = Role::getByName(<span class="hljs-string">'editor'</span>);
<span class="hljs-comment">// 添加枢纽表数据</span><span class="hljs-regexp">$user</span>->roles()->attach(<span class="hljs-regexp">$role</span>);
<span class="hljs-keyword">return</span> <span class="hljs-string">'用户角色添加成功'</span>;
}
```
```
或者直接使用角色Id添加关联数据
```
<pre class="calibre18">
```
<span class="hljs-comment">// 关联新增数据</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span><span class="hljs-number">()</span></span>{
<span class="hljs-regexp">$user</span> = UserModel::getByNickname(<span class="hljs-string">'张三'</span>);
<span class="hljs-regexp">$user</span>->roles()->attach(<span class="hljs-number">1</span>);
<span class="hljs-keyword">return</span> <span class="hljs-string">'用户角色添加成功'</span>;
}
```
```
### 关联删除
如果需要解除用户的管理角色,可以使用`detach`方法删除关联的枢纽表数据,但不会删除关联模型数据,例如:
```
<pre class="calibre18">
```
<span class="hljs-comment">// 关联删除数据</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">delete</span><span class="hljs-number">()</span></span>{
<span class="hljs-regexp">$user</span> = UserModel::get(<span class="hljs-number">2</span>);
<span class="hljs-regexp">$role</span> = Role::getByName(<span class="hljs-string">'admin'</span>);
<span class="hljs-comment">// 删除关联数据 但不删除关联模型数据</span><span class="hljs-regexp">$user</span>->roles()->detach(<span class="hljs-regexp">$role</span>);
<span class="hljs-keyword">return</span> <span class="hljs-string">'用户角色删除成功'</span>;
}
```
```
如果有必要,也可以删除枢纽表的同时删除关联模型,下面的例子会解除用户的编辑角色并且同时删除编辑这个角色身份:
```
<pre class="calibre18">
```
<span class="hljs-comment">// 关联删除数据</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">delete</span><span class="hljs-number">()</span></span>{
<span class="hljs-regexp">$user</span> = UserModel::getByNickname(<span class="hljs-string">'张三'</span>);
<span class="hljs-regexp">$role</span> = Role::getByName(<span class="hljs-string">'editor'</span>);
<span class="hljs-comment">// 删除关联数据 并同时删除关联模型数据</span><span class="hljs-regexp">$user</span>->roles()->detach(<span class="hljs-regexp">$role</span>,<span class="hljs-keyword">true</span>);
<span class="hljs-keyword">return</span> <span class="hljs-string">'用户角色删除成功'</span>;
}
```
```
### 关联查询
获取用户张三的所有角色的话,直接使用:
```
<pre class="calibre18">
```
<span class="hljs-comment">// 关联查询</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">read</span><span class="hljs-number">()</span></span>{
<span class="hljs-regexp">$user</span> = UserModel::getByNickname(<span class="hljs-string">'张三'</span>);
dump(<span class="hljs-regexp">$user</span>->roles);
}
```
```
同样支持对多对多关联使用预载入查询:
```
<pre class="calibre18">
```
<span class="hljs-comment">// 关联查询</span><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">read</span><span class="hljs-number">()</span></span>{
<span class="hljs-comment">// 预载入查询</span><span class="hljs-regexp">$user</span> = UserModel::get(<span class="hljs-number">2</span>,<span class="hljs-string">'roles'</span>);
dump(<span class="hljs-regexp">$user</span>->roles);
}
```
```
到目前为止,我们已经掌握了关联的基础用法,更多的关联使用请关注后续相关的专题。
- 脕茫隆垄脨貌脩脭
- 脕茫隆垄脨貌脩脭
- 脪禄隆垄禄霉麓隆
- 脪禄隆垄禄霉麓隆
- 露镁隆垄URL潞脥脗路脫脡
- 露镁隆垄URL潞脥脗路脫脡
- 脠媒隆垄脟毛脟贸潞脥脧矛脫娄
- 脠媒隆垄脟毛脟贸潞脥脧矛脫娄
- 脣脛隆垄脢媒戮脻驴芒
- 脣脛隆垄脢媒戮脻驴芒
- 脦氓隆垄虏茅脩炉脫茂脩脭
- 脦氓隆垄虏茅脩炉脫茂脩脭
- 脕霉隆垄脛拢脨脥潞脥鹿脴脕陋
- 拢篓1拢漏脛拢脨脥露篓脪氓
- 拢篓2拢漏禄霉麓隆虏脵脳梅
- 拢篓3拢漏露脕脠隆脝梅潞脥脨脼赂脛脝梅
- 拢篓4拢漏脌脿脨脥脳陋禄禄潞脥脳脭露炉脥锚鲁脡
- 拢篓5拢漏虏茅脩炉路露脦搂
- 拢篓6拢漏脢盲脠毛潞脥脩茅脰陇
- 拢篓7拢漏鹿脴脕陋
- 拢篓8拢漏脛拢脨脥脢盲鲁枚
- 脝脽隆垄脢脫脥录潞脥脛拢掳氓
- 脝脽隆垄脢脫脥录潞脥脛拢掳氓
- 掳脣隆垄碌梅脢脭潞脥脠脮脰戮
- 掳脣隆垄碌梅脢脭潞脥脠脮脰戮
- 戮脜隆垄API驴陋路垄
- 戮脜隆垄API驴陋路垄
- 脢庐隆垄脙眉脕卯脨脨鹿陇戮脽
- 脢庐隆垄脙眉脕卯脨脨鹿陇戮脽
- 脢庐脪禄隆垄脌漏脮鹿
- 脢庐脪禄隆垄脌漏脮鹿
- 脢庐露镁隆垄脭脫脧卯
- Cookie
- Session
- 碌楼脭陋虏芒脢脭
- 脥录脧帽麓娄脌铆
- 脦脛录镁脡脧麓芦
- 脩茅脰陇脗毛
- 赂陆脗录
- A隆垄鲁拢录没脦脢脤芒录炉
- B隆垄3.2潞脥5.0脟酶卤冒
- C隆垄脰煤脢脰潞炉脢媒
- 路卢脥芒脝陋拢潞脩搂脧掳ThinkPHP5碌脛脮媒脠路脳脣脢脝
- 路卢脥芒脝陋拢潞脩搂脧掳ThinkPHP5碌脛脮媒脠路脳脣脢脝