多态关联
多态多态,顾名思义,关联得到的对象类型取决于当前状态。
多态关联允许一个模型在单个关联方法中关联一个以上其它模型。
多态关联是动态的,关联的对象取决于多态字段。
使用多态关联的前提
模型 A 多态关联模型 C,模型 C 对应的数据表必须有两个多态字段,其中一个多态字段存着模型 A 对应的数据表的主键,另一个多态字段存着模型 A 对应的数据表的表名称。
多态关联种类
多态关联分为多态一对多关联和多态一对一关联。
多态一对多关联
以 ThinkPHP 官方手册的例子为例,例如用户可以评论书或文章,但评论表通常都是共用同一张数据表,多态一对多关联关系,就是为了满足类似的使用场景而设计。
以 ThinkPHP 官方手册的例子为例子,下面是关联表的数据表结构:
// 文章表
article
id - integer // 文章表主键
title - string // 文章标题
content - text // 文章内容
// 书籍表
book
id - integer // 书籍表主键
title - string // 书籍标题
// 评论表
comment
id - integer // 评论表主键
content - text // 评论内容
commentable_id - integer // 多态 id 字段,当前例子存文章表或书籍表的主键
commentable_type - string // 多态类型字段,当前例子存 article 或 book
一个文章(书籍)有多个评论(一对多),文章表和书籍表共用同一张评论表,这就是多态一对多。如果要使用多态关联,评论表必须设计成这样的结构。
有两个需要注意的字段是 comment
表中的 commentable_id
字段和 commentable_type
字段我们称之为多态字段。其中,commentable_id
用于存放书籍表或者文章表的 id(主键),而 commentable_type
用于存放该评论所属的表的表名称(article
或 book
),通过这样的表设计,我们可以清楚的知道当前评论属于哪篇文章或哪本书籍。通常多态字段的设计是有一个公共的前缀(例如这里用的 commentable
),当然,也支持设置完全不同的字段名(例如用 data_id
和 type
)。
多态一对多关联定义
文章表模型:
<?php
namespace app\index\model;
use think\Model;
class Article extends Model
{
/**
* 获取所有属于文章的评论。
*/
public function comments()
{
// Article 模型多态一对多关联 Comment 模型
return $this->morphMany('Comment', 'commentable');
// 完整写法
// return $this->morphMany('Comment', 'commentable', 'Article');
}
}
morphMany
方法的参数如下:
morphMany('关联模型', '多态字段前缀或数组', '多态类型');
关联模型(必须):关联的模型名称,可以使用模型名(如 Comment
)或者完整的命名空间模型名(如 app\index\model\Comment
)。
多态字段前缀或数组(可选):如果是字符串则表示多态字段的前缀(多态前缀_type
和 多态前缀_id)
,如果是数组,使用 ['多态类型字段名', '多态ID字段名'] 的格式,默认为当前的关联方法名作为字段前缀(当前例子默认为 comments
)。
多态类型(可选):当前模型对应的多态类型,默认为当前模型名,可以使用模型名(如 Article 或 Book
)或者完整的命名空间模型名(如 app\index\model\Article
或
app\index\model\Book
)。
书籍表模型:
<?php
namespace app\index\model;
use think\Model;
class Book extends Model
{
/**
* 获取所有属于书籍的评论。
*/
public function comments()
{
// Book 模型多态一对多关联 Comment 模型
return $this->morphMany('Comment', 'commentable');
// 完整写法
// return $this->morphMany('Comment', 'commentable', 'Book');
}
}
书籍模型的设置方法同文章模型一致,区别在于多态类型不同,但由于多态类型默认会取当前模型名,因此不需要单独设置。
评论表模型
<?php
namespace app\index\model;
use think\Model;
class Comment extends Model
{
/**
* 获取评论对应的多态模型。
*/
public function commentable()
{
return $this->morphTo(); // 当前例子获取 Article 模型或 Book 模型
}
}
morphTo
方法的参数如下:
morphTo('多态字段前缀或数组', ['多态类型别名']);
多态字段前缀或数组(可选):如果是字符串则表示多态字段的前缀,如果是数组,使用['多态类型字段名', '多态ID字段名'] 的格式,默认为当前的关联方法名作为多态字段前缀(当前例子为 commentable
)。
多态类型别名(可选):数组方式定义。
Comment
模型的 commentable
关联会返回 Article
或 Book
模型的对象实例,这取决于评论的多态类型字段值。
morphTo
方法正如我在文章开头说的那样,多态关联允许一个模型在单个关联方法中关联一个以上其它模型。
多态一对一关联
多态一对一关联与多态一对多关联的区别就像一对一关联和一对多关联。以 ThinkPHP 官方手册的例子为例,有一个个人表和一个团队表,而无论是个人还是团队都有一个头像需要保存,而且他们共用同一张头像表,并且无论是个人还是团队都只能拥有一个头像,数据表结构如下
// 会员表
member
id - integer // 会员表主键
name - string
// 团队表
team
id - integer // 团队表主键
name - string
// 头像表
avatar
id - integer // 头像表主键
avatar - string
avatartable_id - integer // 多态 id 字段,当前例子存会员表主键或团队表主键
avatartable_type - string // 多态类型字段,当前例子存 member 或 team
一位会员或一个团队都是只有一个头像(一对一),会员表和团队表共用同一张头像表,这就是多态一对一。如果要使用多态关联,头像表必须设计成这样的表结构。
avatar
表中的 avatartable_id
字段和 avatar_type
字段我们称之为多态字段。其中,avatartable_id
用于存放会员表或者团队表的 id(主键),而 avatar_type
用于存放头像所属的表的表名称( member
或 team
) ,通过这样的表设计,我们可以清楚的知道当前头像属于哪位会员或哪个团队。通常多态字段的设计是有一个公共的前缀(例如这里用的 avatartable
),当然,也支持设置完全不同的字段名(例如用 data_id
和 type
)
会员模型:
<?php
namespace app\index\model;
use think\Model;
class Member extends Model
{
/**
* 获取用户的头像
*/
public function avatar()
{
// Member 模型多态一对一关联 Avatar 模型
return $this->morphOne('Avatar', 'avatartable');
// 完整写法
// return $this->morphOne('Avatar', 'avatartable', 'Member');
}
}
morphOne
方法的参数如下:
morphOne('关联模型', '多态字段前缀或数组', '多态类型');
关联模型(必须):关联的模型名称,可以使用模型名(如 Avatar
)或者完整的命名空间模型名(如 app\index\model\Avatar
)。
多态字段前缀或数组(可选):如果是字符串则表示多态字段的前缀(多态前缀_type
和 多态前缀_id)
,如果是数组,使用 ['多态类型字段名', '多态ID字段名'] 的格式,默认为当前的关联方法名作为字段前缀(当前例子默认为 avatar
)。
多态类型(可选):当前模型对应的多态类型,默认为当前模型名(Member
),可以使用模型名(如 Member
)或者完整的命名空间模型名(如 app\index\model\Member
)。
团队模型:
<?php
namespace app\index\model;
use think\Model;
class Team extends Model
{
/**
* 获取团队的头像
*/
public function avatar()
{
// Team 模型多态一对一关联 Avatar 模型
return $this->morphOne('Avatar', 'avatartable');
// 完整写法
// return $this->morphOne('Avatar', 'avatartable', 'Team');
}
}
团队模型的设置方法同会员模型一致,区别在于多态类型不同,但由于多态类型默认会取当前模型名,因此不需要单独设置。
头像模型:
<?php
namespace app\index\model;
use think\Model;
class Avatar extends Model
{
/**
* 获取头像对应的多态模型。
*/
public function avatartable()
{
return $this->morphTo(); // 当前例子获取 Member 模型或 Team 模型
}
}
morphTo
方法的参数如下:
morphTo('多态字段前缀或数组', ['多态类型别名']);
多态字段前缀或数组(可选):如果是字符串则表示多态字段的前缀,如果是数组,使用['多态类型字段名', '多态ID字段名'] 的格式,默认为当前的关联方法名作为多态字段前缀(当前例子默认为 avatartable
)。
多态类型别名(可选):数组方式定义。
Avatar
模型的 avatartable
关联会返回 Member
或 Team
模型的对象实例,这取决于头像的多态类型字段值。
morphTo 方法正像我在文章开头说的那样,多态关联允许一个模型在单个关联方法中关联一个以上其它模型。
理解了多态一对多关联后,多态一对一关联其实就很容易理解了,区别就是当前模型和动态关联的模型之间的关联属于一对一关系。
总结
多态多态,顾名思义,关联得到的对象类型取决于当前状态。
多态关联允许一个模型在单个关联方法中关联一个以上其它模型。
多态关联是动态的,关联的对象取决于多态字段。
实例演示
演示1
获取 article_id 为 1 的文章详情以及属于它的评论,一篇文章有多个评论,所以使用的是多态一对多 morphMany
方法。
Article 控制器
<?php
declare(strict_types=1);
namespace app\api\controller;
use app\api\model\Article as ArticleModel;
class Article extends Base
{
// 获取文章详情以及属于文章自己的评论
public function detail()
{
$article_id = 1;
$detail = ArticleModel::getDetail($article_id);
echo '<pre>';
var_dump($detail);
echo '</pre>';
}
}
Article 模型
<?php
namespace app\api\model;
class Article extends Base
{
// 因为主键不是默认的名称,所以要重新定义主键名称
protected $pk = 'article_id';
public static function getDetail($article_id)
{
// 预载入关联查询
// 第二个参数是所用到的关联方法的方法名
$detail = self::get($article_id, 'comments');
return $detail;
}
// 多态一对多获取文章的所有评论
public function comments()
{
/*
第二个参数多态字段前缀默认为当前方法名 comments,数据表中的多态字段前缀是
comment_table,所以要自己手动输入。
第三个参数多态字段类型默认为当前模型名 Article,实际上多态字段类型应该是 article,
所以也要自己手动输入
*/
return $this->morphMany('Comment', 'comment_table', 'article');
}
}
Comment 模型
<?php
namespace app\api\model;
class Comment extends Base
{
}
Article 控制器 的 detail 方法输出如下
object(app\api\model\Article)#41 (2) {
["data"]=>
array(6) {
["article_id"]=>
int(1)
["title"]=>
string(12) "测试标题"
["content"]=>
string(12) "测试内容"
["user_id"]=>
int(1)
["create_time"]=>
int(1689401566)
["update_time"]=>
int(1689401566)
}
["relation"]=>
array(1) {
["comments"]=>
object(think\model\Collection)#50 (1) {
["items":protected]=>
array(2) {
[0]=>
object(app\api\model\Comment)#45 (2) {
["data"]=>
array(6) {
["comment_id"]=>
int(1)
["content"]=>
string(30) "文章写得很好,点个赞"
["comment_table_id"]=>
int(1)
["comment_table_type"]=>
string(7) "article"
["create_time"]=>
int(1689401637)
["update_time"]=>
int(1689401637)
}
["relation"]=>
array(0) {
}
}
[1]=>
object(app\api\model\Comment)#46 (2) {
["data"]=>
array(6) {
["comment_id"]=>
int(2)
["content"]=>
string(36) "文章写得很好,下次别写了"
["comment_table_id"]=>
int(1)
["comment_table_type"]=>
string(7) "article"
["create_time"]=>
int(1689403338)
["update_time"]=>
int(1689403338)
}
["relation"]=>
array(0) {
}
}
}
}
}
}
单条查询输出的是文章(Article )模型实例,文章模型实例的 relation 属性(关联数组)保存着关联模型,在该关联数组中,关联方法名 comments 作为键名,结果集对象作为键值,结果集对象的 items 属性(索引数组)保存着关联查询结果。
使用到的 SQL
SELECT * FROM `shop_article` WHERE `article_id` = 1 LIMIT 1
SELECT * FROM `shop_comment` WHERE `comment_table_id` = 1 AND `comment_table_type` = 'article'
获取文章的评论,访问关联方法名即可,
<?php
declare(strict_types=1);
namespace app\api\controller;
use app\api\model\Article as ArticleModel;
class Article extends Base
{
public function detail()
{
$article_id = 1;
$detail = ArticleModel::getDetail($article_id);
echo '<pre>';
var_dump($detail->comments);
echo '</pre>';
}
}
输出如下
object(think\model\Collection)#50 (1) {
["items":protected]=>
array(2) {
[0]=>
object(app\api\model\Comment)#45 (2) {
["data"]=>
array(6) {
["comment_id"]=>
int(1)
["content"]=>
string(30) "文章写得很好,点个赞"
["comment_table_id"]=>
int(1)
["comment_table_type"]=>
string(7) "article"
["create_time"]=>
int(1689401637)
["update_time"]=>
int(1689401637)
}
["relation"]=>
array(0) {
}
}
[1]=>
object(app\api\model\Comment)#46 (2) {
["data"]=>
array(6) {
["comment_id"]=>
int(2)
["content"]=>
string(36) "文章写得很好,下次别写了"
["comment_table_id"]=>
int(1)
["comment_table_type"]=>
string(7) "article"
["create_time"]=>
int(1689403338)
["update_time"]=>
int(1689403338)
}
["relation"]=>
array(0) {
}
}
}
}
输出结果集对象,结果集对象的 items 属性(数组)保存着当前文章的所有评论,如下
演示二
获取所有的文章以及属于它自己的评论
Article 控制器
<?php
declare(strict_types=1);
namespace app\api\controller;
use app\api\model\Article as ArticleModel;
class Article extends Base
{
// 获取所有文章以及属于文章自己的评论
public function list()
{
$list = ArticleModel::getList();
echo '<pre>';
var_dump($list);
echo '</pre>';
}
}
Article 模型
<?php
namespace app\api\model;
class Article extends Base
{
protected $pk = 'article_id';
// 获取全部文章以及属于文章的评论
public static function getList()
{
// 关联预载入
// 参数为所用到的关联方法名称
return self::with('comments')->select();
}
// 多态一对多获取文章的所有评论
public function comments()
{
return $this->morphMany('Comment', 'comment_table', 'article');
}
}
Article 控制器的 list 方法输出
object(think\model\Collection)#43 (1) {
["items":protected]=>
array(2) {
[0]=>
object(app\api\model\Article)#41 (2) {
["data"]=>
array(6) {
["article_id"]=>
int(1)
["title"]=>
string(12) "测试标题"
["content"]=>
string(12) "测试内容"
["user_id"]=>
int(1)
["create_time"]=>
int(1689401566)
["update_time"]=>
int(1689401566)
}
["relation"]=>
array(1) {
["comments"]=>
object(think\model\Collection)#51 (1) {
["items":protected]=>
array(2) {
[0]=>
object(app\api\model\Comment)#46 (2) {
["data"]=>
array(6) {
["comment_id"]=>
int(1)
["content"]=>
string(30) "文章写得很好,点个赞"
["comment_table_id"]=>
int(1)
["comment_table_type"]=>
string(7) "article"
["create_time"]=>
int(1689401637)
["update_time"]=>
int(1689401637)
}
["relation"]=>
array(0) {
}
}
[1]=>
object(app\api\model\Comment)#47 (2) {
["data"]=>
array(6) {
["comment_id"]=>
int(2)
["content"]=>
string(36) "文章写得很好,下次别写了"
["comment_table_id"]=>
int(1)
["comment_table_type"]=>
string(7) "article"
["create_time"]=>
int(1689403338)
["update_time"]=>
int(1689403338)
}
["relation"]=>
array(0) {
}
}
}
}
}
}
[1]=>
object(app\api\model\Article)#42 (2) {
["data"]=>
array(6) {
["article_id"]=>
int(2)
["title"]=>
string(13) "测试标题1"
["content"]=>
string(13) "测试内容1"
["user_id"]=>
int(1)
["create_time"]=>
int(1689498967)
["update_time"]=>
int(1689498967)
}
["relation"]=>
array(1) {
["comments"]=>
object(think\model\Collection)#52 (1) {
["items":protected]=>
array(0) {
}
}
}
}
}
}
多条查询返回由多个文章模型组成的结果集对象,每个文章模型对象的 relation 属性(关联数组)保存着关联查询得到的结果集对象,其中键名是所用到的关联方法名,键值是结果集对象,结果集对象的 items 属性(数组)保存着关联查询结果。
使用的 SQL
SELECT * FROM `shop_article`
SELECT * FROM `shop_comment` WHERE `comment_table_id` IN (1,2) AND `comment_table_type` = 'article'
获取每篇文章的评论
<?php
declare(strict_types=1);
namespace app\api\controller;
use app\api\model\Article as ArticleModel;
class Article extends Base
{
public function list()
{
$list = ArticleModel::getList();
foreach ($list as $article) {
echo '<pre>';
var_dump($article['comments']);
echo '</pre>';
}
}
}
访问关联方法名即可,输出如下
object(think\model\Collection)#51 (1) {
["items":protected]=>
array(2) {
[0]=>
object(app\api\model\Comment)#46 (2) {
["data"]=>
array(6) {
["comment_id"]=>
int(1)
["content"]=>
string(30) "文章写得很好,点个赞"
["comment_table_id"]=>
int(1)
["comment_table_type"]=>
string(7) "article"
["create_time"]=>
int(1689401637)
["update_time"]=>
int(1689401637)
}
["relation"]=>
array(0) {
}
}
[1]=>
object(app\api\model\Comment)#47 (2) {
["data"]=>
array(6) {
["comment_id"]=>
int(2)
["content"]=>
string(36) "文章写得很好,下次别写了"
["comment_table_id"]=>
int(1)
["comment_table_type"]=>
string(7) "article"
["create_time"]=>
int(1689403338)
["update_time"]=>
int(1689403338)
}
["relation"]=>
array(0) {
}
}
}
}
object(think\model\Collection)#52 (1) {
["items":protected]=>
array(0) {
}
}
演示三
获取 comment_id 为 1 的评论详情以及关联它的多态类型,使用的是 morphTo 方法。
comment 控制器
<?php
declare(strict_types=1);
namespace app\api\controller;
use app\api\model\Comment as CommentModel;
class Comment extends Base
{
public function detail()
{
$comment_id = 1;
$detail = CommentModel::getDetail($comment_id);
echo '<pre>';
var_dump($detail);
echo '</pre>';
}
}
comment 模型
<?php
namespace app\api\model;
class Comment extends Base
{
protected $pk = 'comment_id';
public static function getDetail($comment_id)
{
return self::get($comment_id, 'commentTable');
}
// 获取评论对应的多态模型
public function commentTable()
{
// 多态字段前缀默认为当前方法名,因为当前方法名为小驼峰命名法,tp5 会自动转化成下划线法命名
// 即 comment_table
return $this->morphTo();
// 完整写法
// return $this->morphTo('comment_table');
}
}
comment 控制器的 detail 方法输出
object(app\api\model\Comment)#40 (2) {
["data"]=>
array(6) {
["comment_id"]=>
int(1)
["content"]=>
string(30) "文章写得很好,点个赞"
["comment_table_id"]=>
int(1)
["comment_table_type"]=>
string(7) "article"
["create_time"]=>
int(1689401637)
["update_time"]=>
int(1689401637)
}
["relation"]=>
array(1) {
["comment_table"]=>
object(app\api\model\Article)#45 (2) {
["data"]=>
array(6) {
["article_id"]=>
int(1)
["title"]=>
string(12) "测试标题"
["content"]=>
string(12) "测试内容"
["user_id"]=>
int(1)
["create_time"]=>
int(1689401566)
["update_time"]=>
int(1689401566)
}
["relation"]=>
array(0) {
}
}
}
}
Comment 模型实例的 relation 属性(数组)保存关联查询结果 ,其中关联方法名 comment_table 作为键名,关联查询结果作为键值(对一关联查询返回模型实例,对多关联查询返回结果集对象)。
使用的 SQL
SELECT * FROM `shop_comment` WHERE `comment_id` = 1 LIMIT 1
SELECT * FROM `shop_article` WHERE `article_id` = 1 LIMIT 1
获取评论关联的多态类型,访问关联方法名即可
<?php
declare(strict_types=1);
namespace app\api\controller;
use app\api\model\Comment as CommentModel;
class Comment extends Base
{
public function detail()
{
$comment_id = 1;
$detail = CommentModel::getDetail($comment_id);
echo '<pre>';
var_dump($detail->commentTable);
echo '</pre>';
}
}
输出如下
object(app\api\model\Article)#41 (2) {
["data"]=>
array(6) {
["article_id"]=>
int(1)
["title"]=>
string(12) "测试标题"
["content"]=>
string(12) "测试内容"
["user_id"]=>
int(1)
["create_time"]=>
int(1689401566)
["update_time"]=>
int(1689401566)
}
["relation"]=>
array(0) {
}
}
演示四
获取所有评论以及评论对应的多态类型
comment 控制器
<?php
declare(strict_types=1);
namespace app\api\controller;
use app\api\model\Comment as CommentModel;
class Comment extends Base
{
public function list()
{
$list = CommentModel::getList();
echo '<pre>';
var_dump($list);
echo '</pre>';
}
}
comment 模型
<?php
namespace app\api\model;
class Comment extends Base
{
protected $pk = 'comment_id';
// 获取所有评论以及评论对应的多态类型
public static function getList()
{
return self::with('commentTable')->select();
}
// 获取评论对应的多态模型
public function commentTable()
{
return $this->morphTo();
}
}
Comment 控制器 list 方法输出
object(think\model\Collection)#44 (1) {
["items":protected]=>
array(3) {
[0]=>
object(app\api\model\Comment)#40 (2) {
["data"]=>
array(6) {
["comment_id"]=>
int(1)
["content"]=>
string(30) "文章写得很好,点个赞"
["comment_table_id"]=>
int(1)
["comment_table_type"]=>
string(7) "article"
["create_time"]=>
int(1689401637)
["update_time"]=>
int(1689401637)
}
["relation"]=>
array(1) {
["comment_table"]=>
object(app\api\model\Article)#47 (2) {
["data"]=>
array(6) {
["article_id"]=>
int(1)
["title"]=>
string(12) "测试标题"
["content"]=>
string(12) "测试内容"
["user_id"]=>
int(1)
["create_time"]=>
int(1689401566)
["update_time"]=>
int(1689401566)
}
["relation"]=>
array(0) {
}
}
}
}
[1]=>
object(app\api\model\Comment)#42 (2) {
["data"]=>
array(6) {
["comment_id"]=>
int(2)
["content"]=>
string(36) "文章写得很好,下次别写了"
["comment_table_id"]=>
int(1)
["comment_table_type"]=>
string(7) "article"
["create_time"]=>
int(1689403338)
["update_time"]=>
int(1689403338)
}
["relation"]=>
array(1) {
["comment_table"]=>
object(app\api\model\Article)#47 (2) {
["data"]=>
array(6) {
["article_id"]=>
int(1)
["title"]=>
string(12) "测试标题"
["content"]=>
string(12) "测试内容"
["user_id"]=>
int(1)
["create_time"]=>
int(1689401566)
["update_time"]=>
int(1689401566)
}
["relation"]=>
array(0) {
}
}
}
}
[2]=>
object(app\api\model\Comment)#43 (2) {
["data"]=>
array(6) {
["comment_id"]=>
int(3)
["content"]=>
string(30) "视频做得很好,点个赞"
["comment_table_id"]=>
int(1)
["comment_table_type"]=>
string(5) "video"
["create_time"]=>
int(1689473711)
["update_time"]=>
int(1689473711)
}
["relation"]=>
array(1) {
["comment_table"]=>
object(app\api\model\Video)#46 (2) {
["data"]=>
array(5) {
["video_id"]=>
int(1)
["title"]=>
string(12) "视频测试"
["user_id"]=>
int(1)
["create_time"]=>
int(1689473536)
["update_time"]=>
int(1689473536)
}
["relation"]=>
array(0) {
}
}
}
}
}
}
多条查询返回由多个评论模型实例组成的结果集对象,每个评论模型实例的 relation 属性(关联数组)保存着关联查询得到的关联模型实例,其中键名是所用到的关联方法名,键值是关联查询得到的关联模型实例(因为关联方法 morphTo() 是对一关联,所以键值是关联模型实例,如果关联方法是对多关联,则键值是结果集对象)。
使用的 SQL
SELECT * FROM `shop_comment`
SELECT * FROM `shop_article` WHERE `article_id` = 1
SELECT * FROM `shop_video` WHERE `video_id` = 1
获取每个评论关联的多态类型,访问关联方法名即可
<?php
declare(strict_types=1);
namespace app\api\controller;
use app\api\model\Comment as CommentModel;
class Comment extends Base
{
public function list()
{
$list = CommentModel::getList();
foreach ($list as $value) {
echo '<pre>';
var_dump($value['commentTable']);
echo '</pre>';
}
}
}
输出如下
object(app\api\model\Article)#41 (2) {
["data"]=>
array(6) {
["article_id"]=>
int(1)
["title"]=>
string(12) "测试标题"
["content"]=>
string(12) "测试内容"
["user_id"]=>
int(1)
["create_time"]=>
int(1689401566)
["update_time"]=>
int(1689401566)
}
["relation"]=>
array(0) {
}
}
object(app\api\model\Article)#53 (2) {
["data"]=>
array(6) {
["article_id"]=>
int(1)
["title"]=>
string(12) "测试标题"
["content"]=>
string(12) "测试内容"
["user_id"]=>
int(1)
["create_time"]=>
int(1689401566)
["update_time"]=>
int(1689401566)
}
["relation"]=>
array(0) {
}
}
object(app\api\model\Video)#55 (2) {
["data"]=>
array(5) {
["video_id"]=>
int(1)
["title"]=>
string(12) "视频测试"
["user_id"]=>
int(1)
["create_time"]=>
int(1689473536)
["update_time"]=>
int(1689473536)
}
["relation"]=>
array(0) {
}
}