详解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开发负载均衡指南
Jul 17 PHP
php中转义mysql语句的实现代码
Jun 24 PHP
提示Trying to clone an uncloneable object of class Imagic的解决
Oct 27 PHP
深入PHP nl2br()格式化输出的详解
Jun 05 PHP
PHP中的替代语法介绍
Jan 09 PHP
php实现json编码的方法
Jul 30 PHP
学习php设计模式 php实现享元模式(flyweight)
Dec 07 PHP
在Thinkphp中使用ajax实现无刷新分页的方法
Oct 25 PHP
php中简单的对称加密算法实现
Jan 05 PHP
使用PHP连接数据库_实现用户数据的增删改查的整体操作示例
Sep 01 PHP
YII框架关联查询操作示例
Apr 29 PHP
PHP大文件切割上传并带进度条功能示例
Jul 01 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中url函数介绍及使用示例
2014/02/13 PHP
popdiv
2006/07/14 Javascript
国外的为初学者写的JavaScript教程
2008/06/09 Javascript
Jquery ThickBox插件使用心得(不建议使用)
2010/09/08 Javascript
js注意img图片的onerror事件的分析
2011/01/01 Javascript
PHP配置文件php.ini中打开错误报告的设置方法
2015/01/09 PHP
jQuery动态效果显示人物结构关系图的方法
2015/05/07 Javascript
浅谈JavaScript中的分支结构
2016/07/01 Javascript
BootStrap modal模态弹窗使用小结
2016/10/26 Javascript
原生js实现鼠标跟随效果
2017/02/28 Javascript
js自定义Tab选项卡效果
2017/06/05 Javascript
详解Node中导入模块require和import的区别
2017/08/11 Javascript
浅谈 vue 中的 watcher
2017/12/04 Javascript
vue router 跳转后回到顶部的实例
2018/08/31 Javascript
Node.js 使用request模块下载文件的实例
2018/09/05 Javascript
Javascript 之封装(Package)
2018/09/14 Javascript
解决VUE中document.body.scrollTop为0的问题
2018/09/15 Javascript
小程序登录态管理的方法示例
2018/11/13 Javascript
微信小程序通过js实现瀑布流布局详解
2019/08/28 Javascript
JavaScript禁止右击保存图片,禁止拖拽图片的实现代码
2020/04/28 Javascript
用Python实现一个简单的能够上传下载的HTTP服务器
2015/05/05 Python
查找python项目依赖并生成requirements.txt的方法
2018/07/10 Python
pycharm创建一个python包方法图解
2019/04/10 Python
elasticsearch python 查询的两种方法
2019/08/04 Python
Python Gluon参数和模块命名操作教程
2019/12/18 Python
python+Selenium自动化测试——输入,点击操作
2020/03/06 Python
Python基于百度AI实现OCR文字识别
2020/04/02 Python
全球最大的在线橄榄球商店:Lovell Rugby
2018/05/20 全球购物
全球最大运动品牌的男装、女装和童装官方库存商:A&A Sports
2021/01/17 全球购物
会计助理的岗位职责
2013/11/29 职场文书
培训主管岗位职责
2014/02/01 职场文书
《孔繁森》教学反思
2014/04/17 职场文书
学校节能减排倡议书
2014/05/16 职场文书
化学工程专业求职信
2014/08/10 职场文书
《圆的面积》教学反思
2016/02/19 职场文书
Nginx反向代理、重定向
2022/04/13 Servers