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


Posted in PHP onOctober 17, 2019

作为 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的FTP学习(一)[转自奥索]
Oct 09 PHP
将博客园(cnblogs.com)数据导入到wordpress的代码
Jan 06 PHP
php去除换行符的方法小结(PHP_EOL变量的使用)
Feb 16 PHP
用PHP提取中英文词语以及数字的首字母的方法介绍
Apr 23 PHP
php使用mb_check_encoding检查字符串在指定的编码里是否有效
Nov 07 PHP
php构造函数的继承方法
Feb 09 PHP
PHP扩展开发入门教程
Feb 26 PHP
php使用gettimeofday函数返回当前时间并存放在关联数组里
Mar 19 PHP
twig模板常用语句实例小结
Feb 04 PHP
利用PHP实现一个简单的用户登记表示例
Apr 25 PHP
PHP生成二维码与识别二维码的方法详解【附源码下载】
Mar 07 PHP
解决在laravel中auth建立时候遇到的问题
Oct 15 PHP
Laravel 5.5 异常处理 &amp; 错误日志的解决
Oct 17 #PHP
PHP封装请求类实例分析【基于Yii框架】
Oct 17 #PHP
使用laravel指定日志文件记录任意日志
Oct 17 #PHP
Laravel 修改默认日志文件名称和位置的例子
Oct 17 #PHP
thinkPHP事务操作简单案例分析
Oct 17 #PHP
使用laravel根据用户类型来显示或隐藏字段
Oct 17 #PHP
laravel model模型定义实现开启自动管理时间created_at,updated_at
Oct 17 #PHP
You might like
PHP 计算代码执行耗时的代码修正网上普遍错误
2011/05/14 PHP
Yii框架数据模型的验证规则rules()被执行的方法
2016/12/02 PHP
解析js如何获取当前url中的参数值并复制给input
2013/06/23 Javascript
jQuery中prop()方法用法实例
2015/01/05 Javascript
JS动态改变表格边框宽度的方法
2015/03/31 Javascript
js实现的奥运倒计时时钟效果代码
2015/12/09 Javascript
Node.js 异步异常的处理与domain模块解析
2017/05/10 Javascript
require.js中的define函数详解
2017/07/10 Javascript
浅谈node中的exports与module.exports的关系
2017/08/01 Javascript
微信小程序日期选择器实例代码
2018/07/18 Javascript
详解React 服务端渲染方案完美的解决方案
2018/12/14 Javascript
关于vue路由缓存清除在main.js中的设置
2019/11/06 Javascript
微信小程序实现导航栏和内容上下联动功能代码
2020/06/29 Javascript
js实现飞机大战游戏
2020/08/26 Javascript
一篇不错的Python入门教程
2007/02/08 Python
使用python Django做网页
2013/11/04 Python
python33 urllib2使用方法细节讲解
2013/12/03 Python
Python中定时任务框架APScheduler的快速入门指南
2017/07/06 Python
python实现画圆功能
2018/01/25 Python
Python编程求质数实例代码
2018/01/31 Python
python脚本生成caffe train_list.txt的方法
2018/04/27 Python
python 对类的成员函数开启线程的方法
2019/01/22 Python
Python实现操纵控制windows注册表的方法分析
2019/05/24 Python
VPS CENTOS 上配置python,mysql,nginx,uwsgi,django的方法详解
2019/07/01 Python
解决pandas展示数据输出时列名不能对齐的问题
2019/11/18 Python
Pure Collection美国官网:来自英国羊绒专家的奢华羊绒
2017/11/19 全球购物
微软中国官方旗舰店:销售Surface、Xbox One、笔记本电脑、Office
2018/07/23 全球购物
医院护士的求职信范文
2013/12/26 职场文书
致400米运动员广播稿
2014/02/07 职场文书
小学生作文评语
2014/04/18 职场文书
初中同学会活动方案
2014/08/22 职场文书
党员干部民主生活会议批评与自我批评材料
2014/09/20 职场文书
汽车转让协议书
2015/01/29 职场文书
python编写函数注意事项总结
2021/03/29 Python
Python基础详解之邮件处理
2021/04/28 Python
nginx请求限制配置方法
2021/07/09 Servers