详解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 相关文章推荐
Drupal 添加模块出现莫名其妙的错误的解决方法(往往出现在模块较多时)
Apr 18 PHP
PHP数组实例总结与说明
Aug 23 PHP
mysql 查询指定日期时间内sql语句实现原理与代码
Dec 16 PHP
深入for,while,foreach遍历时间比较的详解
Jun 08 PHP
测试php函数的方法
Nov 13 PHP
PHP将字符分解为多个字符串的方法
Nov 22 PHP
php通过asort()给关联数组按照值排序的方法
Mar 18 PHP
分享PHP守护进程类
Dec 30 PHP
非集成环境的php运行环境(Apache配置、Mysql)搭建安装图文教程
Apr 12 PHP
PHP设计模式之模板模式定义与用法详解
Dec 20 PHP
PHP实现的62进制转10进制,10进制转62进制函数示例
Jun 06 PHP
php设计模式之适配器模式原理、用法及注意事项详解
Sep 24 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中,文件上传
2006/12/06 PHP
PHP 的 __FILE__ 常量
2007/01/15 PHP
libmysql.dll与php.ini是否真的要拷贝到c:\windows目录下呢
2010/03/15 PHP
php 无限级分类学习参考之对ecshop无限级分类的解析 带详细注释
2010/03/23 PHP
举例讲解PHP面对对象编程的多态
2015/08/12 PHP
php中session定期自动清理的方法
2015/11/12 PHP
Yii2中事务的使用实例代码详解
2016/09/07 PHP
用window.location.href实现刷新另个框架页面
2007/03/07 Javascript
JavaScript 继承详解(二)
2009/07/13 Javascript
jQuery对象的length属性用法实例
2014/12/27 Javascript
JS实现网页Div层Clone拖拽效果
2015/09/26 Javascript
jquery实现的动态回到顶部特效代码
2015/10/28 Javascript
URL的参数中有加号传值变为空格的问题(URL特殊字符)
2016/11/04 Javascript
JavaScript中String对象的方法介绍
2017/01/04 Javascript
Vue中的vue-resource示例详解
2018/11/02 Javascript
基于elementUI使用v-model实现经纬度输入的vue组件
2019/05/12 Javascript
微信小程序实现批量倒计时功能
2020/11/01 Javascript
微信小程序语音同步智能识别的实现案例代码解析
2020/05/29 Javascript
vue集成openlayers加载geojson并实现点击弹窗教程
2020/09/24 Javascript
python实现数值积分的Simpson方法实例分析
2015/06/05 Python
Python判断一个文件夹内哪些文件是图片的实例
2018/12/07 Python
python实现随机漫步方法和原理
2019/06/10 Python
django框架F&amp;Q 聚合与分组操作示例
2019/12/12 Python
悦木之源美国官网:Origins美国
2016/08/01 全球购物
实现向右循环移位
2014/07/31 面试题
电子商务专业个人的自我评价分享
2013/10/29 职场文书
商场主管竞聘书
2014/03/31 职场文书
房地产资料员岗位职责
2014/07/02 职场文书
软件工程毕业生自荐信
2014/07/04 职场文书
关于教师节的演讲稿
2014/09/04 职场文书
党员干部廉洁自律承诺书
2015/04/28 职场文书
2015年国庆晚会主持词
2015/07/01 职场文书
关于远足的感想
2015/08/10 职场文书
追悼会家属答谢词
2015/09/29 职场文书
vue完美实现el-table列宽自适应
2021/05/08 Vue.js
python中filter,map,reduce的作用
2022/06/10 Python