💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
本篇为您讲述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); } ``` ``` 到目前为止,我们已经掌握了关联的基础用法,更多的关联使用请关注后续相关的专题。