详解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框架的性能
Jan 10 PHP
坏狼的PHP学习教程之第2天
Jun 15 PHP
一步一步学习PHP(4) php 函数 补充2
Feb 15 PHP
PDO防注入原理分析以及使用PDO的注意事项总结
Oct 23 PHP
PHP通过串口实现发送短信
Jul 08 PHP
nginx下安装php7+php5
Jul 31 PHP
PHP设计模式之工厂模式与单例模式
Sep 28 PHP
PHP实现通过strace定位故障原因的方法
Apr 29 PHP
深入研究PHP中的preg_replace和代码执行
Aug 15 PHP
Laravel框架FormRequest中重写错误处理的方法
Feb 18 PHP
PHP实现会员账号单唯一登录的方法分析
Mar 07 PHP
php遍历目录下文件并按修改时间排序操作示例
Jul 12 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
模拟SQLSERVER的两个函数:dateadd(),datediff()
2006/10/09 PHP
php中将图片gif,jpg或mysql longblob或blob字段值转换成16进制字符串
2011/08/23 PHP
php中unserialize返回false的解决方法
2014/09/22 PHP
PHP中echo,print_r与var_dump区别分析
2014/09/29 PHP
php随机生成数字字母组合的方法
2015/03/18 PHP
php生成短域名函数
2015/03/23 PHP
php防止网站被攻击的应急代码
2015/10/21 PHP
CodeIgniter表单验证方法实例详解
2016/03/03 PHP
PHP将整数数字转换为罗马数字实例分享
2019/03/17 PHP
PHP使用PDO 连接与连接管理操作实例分析
2020/04/21 PHP
Avengerls vs Newbee BO3 第二场2.18
2021/03/10 DOTA
jQuery开发者都需要知道的5个小技巧
2010/01/08 Javascript
最佳的addEvent事件绑定是怎样诞生的
2011/10/24 Javascript
使用PHP+JQuery+Ajax分页的实现
2013/04/23 Javascript
angularjs基础教程
2014/12/25 Javascript
jQuery 弹出层插件(推荐)
2016/05/24 Javascript
js中数组的常用方法小结
2016/12/30 Javascript
Angular2 之 路由与导航详细介绍
2017/05/26 Javascript
Vue.js弹出模态框组件开发的示例代码
2017/07/26 Javascript
vue 弹窗时 监听手机返回键关闭弹窗功能(页面不跳转)
2019/05/10 Javascript
layUI使用layer.open,在content打开数据表格,获取值并返回的方法
2019/09/26 Javascript
Vue实现点击箭头上下移动效果
2020/06/11 Javascript
利用js canvas实现五子棋游戏
2020/10/11 Javascript
[03:11]DOTA2上海特锦赛小组赛第一日recap精彩回顾
2016/02/28 DOTA
基于Django与ajax之间的json传输方法
2018/05/29 Python
python GUI库图形界面开发之PyQt5选项卡控件QTabWidget详细使用方法与实例
2020/03/01 Python
意大利文具和办公产品在线商店:Y-Office
2020/02/27 全球购物
档案室主任岗位职责
2014/02/12 职场文书
工程售后服务承诺书
2014/05/21 职场文书
预备党员转正考核材料
2014/06/03 职场文书
中队活动总结
2014/08/27 职场文书
迎七一演讲稿
2014/09/12 职场文书
社保缴纳证明申请书
2014/11/03 职场文书
加班费申请报告
2015/05/15 职场文书
2016年秋季运动会加油稿
2015/12/21 职场文书
剧场版《转生恶役只好拔除破灭旗标》公开最新视觉图 2023年上映
2022/04/02 日漫