详解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 数据库树的遍历方法
Feb 06 PHP
PHP 根据IP地址控制访问的代码
Apr 22 PHP
PHP保留两位小数并且四舍五入及不四舍五入的方法
Sep 22 PHP
zf框架db类的分页示例分享
Mar 14 PHP
PHP实现HTML生成PDF文件的方法
Nov 07 PHP
php中stdClass的用法分析
Feb 27 PHP
PHP之正则表达式捕获组与非捕获组(详解)
Jul 29 PHP
php实现处理输入转义字符的代码
Nov 08 PHP
PHP获取网页所有连接的方法(附demo源码下载)
Mar 30 PHP
PHP正则删除HTML代码中宽高样式的方法
Jun 12 PHP
Laravel框架定时任务2种实现方式示例
Dec 08 PHP
laravel框架语言包拓展实现方法分析
Nov 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输出Excel文件类
2010/02/08 PHP
PHP 文件上传全攻略
2010/04/28 PHP
关于php连接mssql:pdo odbc sql server
2011/07/20 PHP
使用php判断网页是否gzip压缩
2013/06/25 PHP
一个php生成16位随机数的代码(两种方法)
2014/09/16 PHP
php版微信开发之接收消息,自动判断及回复相应消息的方法
2016/09/23 PHP
php5.x禁用eval的操作方法
2018/10/19 PHP
thinkPHP事务操作简单案例分析
2019/10/17 PHP
javascript中的if语句使用介绍
2013/11/20 Javascript
Jquery异步提交表单代码分享
2015/03/26 Javascript
jQuery构造函数init参数分析
2015/05/13 Javascript
js如何实现淡入淡出效果
2020/11/18 Javascript
解决jquery无法找到其他父级子集问题的方法
2016/05/10 Javascript
ionic cordova一次上传多张图片(类似input file提交表单)的实现方法
2016/12/16 Javascript
bootstrap警告框示例代码分享
2017/05/17 Javascript
javascript实现QQ空间相册展示源码
2017/12/12 Javascript
详解给Vue2路由导航钩子和axios拦截器做个封装
2018/04/10 Javascript
vue项目中添加单元测试的方法
2018/07/21 Javascript
JS动画实现回调地狱promise的实例代码详解
2018/11/08 Javascript
JS实现数组去重及数组内对象去重功能示例
2019/02/02 Javascript
vuex管理状态仓库使用详解
2020/07/29 Javascript
js实现简易拖拽的示例
2020/10/26 Javascript
[06:53]DOTA2每周TOP10 精彩击杀集锦vol.3
2014/06/25 DOTA
Python中返回字典键的值的values()方法使用
2015/05/22 Python
浅析Python3爬虫登录模拟
2018/02/07 Python
python 用户交互输入input的4种用法详解
2019/09/24 Python
如何在Python 游戏中模拟引力
2020/03/27 Python
微信小程序canvas实现水平、垂直居中效果
2020/02/05 HTML / CSS
幼儿如何来做好自我评价
2013/11/05 职场文书
护士毕业生自荐信
2014/02/07 职场文书
本溪关门山导游词
2015/02/09 职场文书
2015年春训学习心得体会范文
2015/03/09 职场文书
稽核岗位职责范本
2015/04/13 职场文书
教师思想工作总结2015
2015/05/13 职场文书
mysql聚集索引、辅助索引、覆盖索引、联合索引的使用
2022/02/12 MySQL
Nginx代理Redis哨兵主从配置的实现
2022/07/15 Servers