多态关联

版本 功能调整
5.0.8 支持多态一对一关联
5.0.4 支持多态一对多关联

多态一对多关联(V5.0.4+

多态关联允许一个模型在单个关联定义方法中从属一个以上其它模型,例如用户可以评论书和文章,但评论表通常都是同一个数据表的设计。多态一对多关联关系,就是为了满足类似的使用场景而设计。

下面是关联表的数据表结构:

						article
							id
							-
							integer
							title -
							string
							content -
							text
							book
							id
							-
							integer
							title -
							string
							comment
							id
							-
							integer
							content -
							text
							commentable_id -
							integer
							commentable_type -
							string
						
					

有两个需要注意的字段是comment 表中的commentable_id 和commentable_type我们称之为多态字段。其中,commentable_id 用于存放书或者文章的 id(主键) ,而commentable_type 用于存放所属模型的类型。通常的设计是多态字段有一个公共的前缀(例如这里用的commentable),当然,也支持设置完全不同的字段名(例如使用data_idtype)。

多态关联定义

接着,让我们来查看创建这种关联所需的模型定义:

文章模型:

						
							
								<?php
								namespace
								app\index\model;
								use
								think\Model;
								
									class
									Article
									extends
									Model
								{
								/**      * 获取所有针对文章的评论。      */
								public
								
									function
									comments
									()
								{
								return
								$this->morphMany('Comment',
								'commentable');     } }
							
						
					

morphMany方法的参数如下:

morphMany('关联模型名','多态字段信息','多态类型');

关联模型名(必须):关联的模型名称,可以使用模型名(如Comment)或者完整的命名空间模型名(如app\index\model\Comment)。

多态字段信息(可选):支持两种方式定义 如果是字符串表示多态字段的前缀,多态字段使用多态前缀_type多态前缀_id,如果是数组,表示使用['多态类型字段名','多态ID字段名'],默认为当前的关联方法名作为字段前缀。

多态类型(可选):当前模型对应的多态类型,默认为当前模型名,可以使用模型名(如Article)或者完整的命名空间模型名(如app\index\model\Article)。

书籍模型:

						
							
								<?php
								namespace
								app\index\model;
								use
								think\Model;
								
									class
									Book
									extends
									Model
								{
								/**      * 获取所有针对书籍的评论。      */
								public
								
									function
									comments
									()
								{
								return
								$this->morphMany('Comment',
								'commentable');     } }
							
						
					

书籍模型的设置方法同文章模型一致,区别在于多态类型不同,但由于多态类型默认会取当前模型名,因此不需要单独设置。

下面是评论模型的关联定义:

						
							
								<?php
								namespace
								app\index\model;
								use
								think\Model;
								
									class
									Comment
									extends
									Model
								{
								/**      * 获取评论对应的多态模型。      */
								public
								
									function
									commentable
									()
								{
								return
								$this->morphTo();     } }
							
						
					

morphTo方法的参数如下:

morphTo('多态字段信息',['多态类型别名']);

多态字段信息(可选):支持两种方式定义 如果是字符串表示多态字段的前缀,多态字段使用多态前缀_type多态前缀_id,如果是数组,表示使用['多态类型字段名','多态ID字段名'],默认为当前的关联方法名作为字段前缀
多态类型别名(可选):数组方式定义

获取多态关联

一旦你的数据表及模型被定义,则可以通过模型来访问关联。例如,若要访问某篇文章的所有评论,则可以简单的使用comments 动态属性:

						$article = Article::get(1);
							foreach
							($article->comments
							as
							$comment) {     dump($comment); }
						
					

你也可以从多态模型的多态关联中,通过访问调用morphTo 的方法名称来获取拥有者,也就是此例子中Comment 模型的commentable 方法。所以,我们可以使用动态属性来访问这个方法:

						$comment
							=
							Comment::get(1); $commentable = $comment->commentable;
						
					

Comment 模型的commentable 关联会返回Article 或Book 模型的对象实例,这取决于评论所属模型的类型。

自定义多态关联的类型字段

默认情况下,ThinkPHP 会使用模型名作为多态表的类型区分,例如,Comment属于Article 或者Book ,commentable_type 的默认值可以分别是Article 或者Book 。我们可以通过定义多态的时候传入参数来对数据库进行解耦。

						
							public
							
								function
								commentable
								()
							{
							return
							$this->morphTo('commentable',[
							'book'
							=>
							'app\index\model\Book',
							'post'
							=>
							'app\admin\model\Article',         ]);     }
						
					

多态一对一关联(V5.0.8+

多态一对一相比多态一对多关联的区别是动态的一对一关联,举个例子说有一个个人和团队表,而无论个人还是团队都有一个头像需要保存但都会对应同一个头像表

						member
							id
							-
							integer
							name
							-
							string
							team
							id
							-
							integer
							name
							-
							string
							avatar
							id
							-
							integer
							avatar -
							string
							imageable_id -
							integer
							imageable_type -
							string
						
					

会员模型:

						
							
								<?php
								namespace
								app\index\model;
								use
								think\Model;
								
									class
									Member
									extends
									Model
								{
								/**      * 获取用户的头像      */
								public
								
									function
									avatar
									()
								{
								return
								$this->morphOne('Avatar',
								'imageable');     } }
							
						
					

团队模型:

						
							
								<?php
								namespace
								app\index\model;
								use
								think\Model;
								
									class
									Team
									extends
									Model
								{
								/**      * 获取团队的头像      */
								public
								
									function
									avatar
									()
								{
								return
								$this->morphOne('Avatar',
								'imageable');     } }
							
						
					

morphOne方法的参数如下:

morphOne('关联模型名','多态字段信息','多态类型');

关联模型名(必须):关联的模型名称,可以使用模型名(如Member)或者完整的命名空间模型名(如app\index\model\Member)。

多态字段信息(可选):支持两种方式定义 如果是字符串表示多态字段的前缀,多态字段使用多态前缀_type多态前缀_id,如果是数组,表示使用['多态类型字段名','多态ID字段名'],默认为当前的关联方法名作为字段前缀。

多态类型(可选):当前模型对应的多态类型,默认为当前模型名,可以使用模型名(如Member)或者完整的命名空间模型名(如app\index\model\Member)。

下面是头像模型的关联定义:

						
							
								<?php
								namespace
								app\index\model;
								use
								think\Model;
								
									class
									Avatar
									extends
									Model
								{
								/**      * 获取头像对应的多态模型。      */
								public
								
									function
									imageable
									()
								{
								return
								$this->morphTo();     } }
						
					
文档最后更新时间:2018-06-09 15:41:35

文档
目录

深色
模式

切换
宽度