详解Laravel设置多态关系模型别名的方式

所属分类: 网络编程 / PHP编程 阅读数: 733
收藏 0 赞 0 分享

作为 Laravel 的重度使用者肯定都对多态关系不默生,以官方文档为例,文章有标签,视频有标签,那么文章和视频这些模型与标签模型的关系就是 多态多对多(Many To Many (Polymorphic))

如果我们给 ID 为 1 的文章打上两个标签,数据库标签关系表的的存储结果就是这样子:

> select * from taggables;
+--------+-------------+---------------+
| tag_id | taggable_id | taggable_type |
+--------+-------------+---------------+
|  1 |   1 | App\Post  |
|  2 |   1 | App\Post  |
+--------+-------------+---------------+

相信有不少人和我一样希望 taggable_type 的值不要直接用模型类名,而是使用表名: posts 。官方文档的建议是:

use Illuminate\Database\Eloquent\Relations\Relation;

Relation::morphMap([
 'posts' => 'App\Post',
 'videos' => 'App\Video',
]);

https://laravel.com/docs/6.x/eloquent-relationships#custom-polymorphic-types

我们可以将这个定义写到 AppServiceProvider 中,但是有一个非常严重的问题: 我们在新增或者删除模型的时候,会很容易忘记去更新这个定义 。我已经至少出现这个问题 3 次了,所以我一直在纠结有没有更好的方法,今天突然灵机一动,实现了一个看起来似乎是一个不错的方式,分享给大家。

思路来源

我尝试跟踪了一遍源码,发现模型中有一个方法 getMorphClass ,多态关联的时候,就是用它来取目标对象的类型名称的,默认返回类名:

public function getMorphClass()
{
 $morphMap = Relation::morphMap();
 if (! empty($morphMap) && in_array(static::class, $morphMap)) {
  return array_search(static::class, $morphMap, true);
 }
 return static::class;
}

那么,只要我们在模型中覆盖这个方法便可以方便的实现目标了。

实现目标

我们有两个选择去实现它:

  1. 创建一个模型基类覆盖这个方法,所有的模型都来集成它即可;
  2. 创建一个 trait,在需要的模型中引入它。

我当然会选择 trait 方式来实现,不管从定义还是代码耦合度上,使用 trait 来解决这类特性需求都是再适合不过了,如果你对 trait 还不太熟悉,可以阅读我之前的文章: 《我所理解的 PHP Trait》

我们的目标是使用表名来做为关系类别名,那么在模型中如何获取表名呢,直接使用模型的 getTable 即可,那么整个 trait 的实现如下:

app/Traits/UseTableNameAsMorphClass.php
<?php
namespace App\Traits;
trait UseTableNameAsMorphClass
{
 public function getMorphClass()
 {
  return $this->getTable();
 }
}

然后在我们需要用到关系类型的模型中引入它即可:

<?php
namespace App;
use App\Traits\UseTableNameAsMorphClass;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
 use UseTableNameAsMorphClass;

 //...
}

友情提示

当然,如果你习惯给表名加前缀,或者你的表名与模型名不太一致,那么,你只需要修改 trait 中 getMorphClass 的实现即可,我个人的习惯是模型名就是表名的单数,不带前缀。

以上所述是小编给大家介绍的Laravel设置多态关系模型别名的方式,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

更多精彩内容其他人还在看

两种php去除二维数组的重复项方法

这篇文章主要介绍了两种php去除二维数组的重复项方法,大家可以进行比较看哪一种更适合自己,需要的朋友可以参考下
收藏 0 赞 0 分享

php实现分页功能的3种方法第1/3页

这篇文章主要介绍了php实现分页功能的3种方法,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

php对二维数组进行相关操作(排序、转换、去空白等)

这篇文章主要介绍了php对二维数组进行相关操作,包括php对二维数组排序、转换、去空白,以及去重复值等,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

php实现网站留言板功能

这篇文章主要介绍了php实现网站留言板功能,主要仿照了畅言留言板和网易跟帖样式进行制作,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

PHP实现HTML页面静态化的方法

这篇文章主要介绍了PHP实现HTML页面静态化的方法,分享了静态处理的方法,静态处理后的优势,并提供了多种静态的方法,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

php对文件夹进行相关操作(遍历、计算大小)

这篇文章主要介绍了php对文件夹进行相关操作,包括遍历并打印指定目录下所有文件和计算文件大小去空白,以及去重复值等,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

非常全面的php日期时间运算汇总

这篇文章主要整理了关于php日期时间运算相关内容,涉及知识点较为全面,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

php根据用户语言跳转相应网页

这篇文章主要介绍了php根据用户语言跳转相应网页的方法,主要区分国内国外,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

双冒号 ::在PHP中的使用情况

前几天在百度知道里面看到有人问PHP中双冒号::的用法,当时给他的回答比较简洁因为手机打字不大方便!今天突然想起来,所以在这里总结一下我遇到的双冒号::在PHP中使用的情况
收藏 0 赞 0 分享

PHP explode()函数的几个应用和implode()函数有什么区别

这篇文章主要介绍了PHP explode()函数的几个应用和implode()函数有什么区别,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多