详解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 相关文章推荐
MySQL中create table语句的基本语法是
Jan 15 PHP
Gregarius中文日期格式问题解决办法
Apr 22 PHP
PHP获取163、gmail、126等邮箱联系人地址【已测试2009.10.10】
Oct 11 PHP
有关phpmailer的详细介绍及使用方法
Jan 28 PHP
PHP之短标签开启设置
Jun 17 PHP
php文件缓存类汇总
Nov 21 PHP
PHP扩展程序实现守护进程
Apr 16 PHP
一个简单安全的PHP验证码类、PHP验证码
Sep 24 PHP
PHP中的日期时间处理利器实例(Carbon)
Jun 09 PHP
thinkPHP多表查询及分页功能实现方法示例
Jul 03 PHP
PHP常见过waf webshell以及最简单的检测方法
May 21 PHP
PHP 实现 JSON 数据的编码和解码操作详解
Apr 22 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/07/08 PHP
可以在线执行PHP代码包装修正版
2008/03/15 PHP
使用 MySQL Date/Time 类型
2008/03/26 PHP
用PHP实现的四则运算表达式计算实现代码
2011/08/02 PHP
php跨域cookie共享使用方法
2014/02/20 PHP
php通过记录IP来防止表单重复提交方法分析
2014/12/16 PHP
IE与FireFox的兼容性问题分析
2007/04/22 Javascript
JavaScript Array扩展实现代码
2009/10/14 Javascript
Google的跟踪代码 动态加载js代码方法应用
2012/11/12 Javascript
在WordPress中加入Google搜索功能的简单步骤讲解
2016/01/04 Javascript
seajs学习之模块的依赖加载及模块API的导出
2016/10/20 Javascript
Vue 中批量下载文件并打包的示例代码
2017/11/20 Javascript
Postman模拟发送带token的请求方法
2018/03/31 Javascript
Bootstrap-table使用footerFormatter做统计列功能
2018/09/07 Javascript
BootStrap表单验证中的非Submit类型按钮点击时触发验证的坑
2019/09/05 Javascript
js实现贪吃蛇小游戏(加墙)
2020/07/31 Javascript
跟老齐学Python之私有函数和专有方法
2014/10/24 Python
Python如何为图片添加水印
2016/11/25 Python
Python 专题二 条件语句和循环语句的基础知识
2017/03/19 Python
一篇文章快速了解Python的GIL
2018/01/12 Python
对python:threading.Thread类的使用方法详解
2019/01/31 Python
Python实现九宫格式的朋友圈功能内附“马云”朋友圈
2019/05/07 Python
python并发编程 Process对象的其他属性方法join方法详解
2019/08/20 Python
python中调试或排错的五种方法示例
2019/09/12 Python
pymysql 插入数据 转义处理方式
2020/03/02 Python
python 安装impala包步骤
2020/03/28 Python
Python request操作步骤及代码实例
2020/04/13 Python
俄罗斯小米家用电器、电子产品和智能家居商店:Poood.ru
2020/04/03 全球购物
中兴通讯全球官方网站:ZTE
2020/12/26 全球购物
RealTek面试题
2016/06/28 面试题
酒店经理职责
2014/01/30 职场文书
旅行社各个岗位职责
2014/03/15 职场文书
公司新人试用期自我评价
2014/09/17 职场文书
张思德观后感
2015/06/09 职场文书
MySQL分区路径子分区再分区
2022/04/13 MySQL
Python自动操作神器PyAutoGUI的使用教程
2022/06/16 Python