详解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解析html的实现代码
Aug 08 PHP
js和php邮箱地址验证的实现方法
Jan 09 PHP
PHP实现的多彩标签效果代码分享
Aug 21 PHP
php计算整个mysql数据库大小的方法
Jun 19 PHP
PHP生成和获取XML格式数据的方法
Mar 04 PHP
Yii2配置Nginx伪静态的方法
May 05 PHP
PHP简单实现模拟登陆功能示例
Sep 15 PHP
PHP实现动态获取函数参数的方法示例
Apr 02 PHP
详解php用static方法的原因
Sep 12 PHP
PHP抽象类基本用法示例
Dec 28 PHP
微信公众平台开发教程①获取用户Openid及个人信息图文详解
Apr 10 PHP
PHP dirname功能及原理实例解析
Oct 28 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 时间转换Unix时间戳代码
2010/01/22 PHP
php实现随机生成易于记忆的密码
2015/06/19 PHP
JavaScript实现自动消除按钮功能的方法
2015/08/05 Javascript
Angularjs的ng-repeat中去除重复数据的方法
2016/08/05 Javascript
简单实现js点击展开二级菜单功能
2017/05/16 Javascript
vue2.0中goods选购栏滚动算法的实现代码
2017/05/17 Javascript
Angular 4 依赖注入学习教程之FactoryProvider的使用(四)
2017/06/04 Javascript
基于jQuery中ajax的相关方法汇总(必看篇)
2017/11/08 jQuery
js实现数组内数据的上移和下移的实例
2017/11/14 Javascript
vue的传参方式汇总和router使用技巧
2018/05/22 Javascript
基于vue.js中关于下拉框的值默认及绑定问题
2018/08/22 Javascript
详解如何使用koa实现socket.io官网的例子
2018/11/04 Javascript
Vue自定义指令上报Google Analytics事件统计的方法
2019/02/25 Javascript
JavaScript碎片—函数闭包(模拟面向对象)
2019/03/13 Javascript
vue的滚动条插件实现代码
2019/09/07 Javascript
[40:48]DOTA2上海特级锦标赛D组败者赛 Liquid VS COL第二局
2016/02/28 DOTA
python实现FTP服务器服务的方法
2017/04/11 Python
多版本Python共存的配置方法
2017/05/22 Python
Python对字符串实现去重操作的方法示例
2017/08/11 Python
Python使用Pickle库实现读写序列操作示例
2018/06/15 Python
Python中xml和dict格式转换的示例代码
2019/11/07 Python
最新pycharm安装教程
2020/11/18 Python
详解Python模块化编程与装饰器
2021/01/16 Python
纯CSS3实现自定义Tooltip边框涂鸦风格的教程
2014/11/05 HTML / CSS
全球知名提供各类营养保健品的零售商:Vitamin Shoppe
2016/10/09 全球购物
阿里健康官方海外旗舰店:阿里健康国际自营
2017/11/24 全球购物
世界上最大的罕见唱片、CD和音乐纪念品网上商店:991.com
2018/05/03 全球购物
简述进程的启动、终止的方式以及如何进行进程的查看
2014/02/20 面试题
办理收楼委托书范本
2014/10/09 职场文书
2014年班长个人工作总结
2014/11/14 职场文书
2014年法院个人工作总结
2014/12/17 职场文书
见义勇为事迹材料
2014/12/24 职场文书
贷款承诺书
2015/01/20 职场文书
信用卡催款律师函
2015/05/27 职场文书
让生命充满爱观后感
2015/06/08 职场文书
Spring中bean的生命周期之getSingleton方法
2021/06/30 Java/Android