当前位置: 首页 > news >正文

Laravel 中的一个后期静态绑定

(原文地址,内容以原文为准,可能修改或者补充:https://blog.tanteng.me/2017/...)

关于 PHP 的 new static 延迟静态绑定,或者叫后期静态绑定,在 Laravel 中遇到一个使用上的问题。如下,在 Laravel 中调用 Model 新增数据的时候,首先给 Model 加了一个获取分表的方法:

protected function addToMessage($msgType, $userID, $commentID, $replyCommentID, $replyUserID, $gameID)
{
    if (!$userID) {
        return false;
    }
 
    $table = 't_message_' . hashID($userID, 100);
    $this->message->setTable($table)->create([
        'msg_type'         => $msgType,
        'user_id'          => $userID,
        'comment_id'       => $commentID,
        'reply_comment_id' => $replyCommentID,
        'reply_user_id'    => $replyUserID,
        'game_id'          => $gameID,
        'is_read'          => 0,
        'created_at'       => date('Y-m-d H:i:s'),
    ]);
    return true;
}

这里 setTable 方法是在 Model 里定义的获取分表的方法:

public function setTable($table)
{
    $this->table = $table;
    return $this;
}

从报错日志中发现 $this->table 并没有生效,但实际上在调用 create 方法之前打印表名的时候是期望的值,这里调用 create 方法为什么 $this->table 没有被重置呢?

这里 $this->message 是一个继承 Model 类的模型类,其中 create 方法:

public static function create(array $attributes = [])
{
    $model = new static($attributes);
 
    $model->save();
 
    return $model;
}

位于 vendorlaravelframeworksrcIlluminateDatabaseEloquentModel.php Line 557.

因为 Laravel 框架的这个 Model 类是一个 abstract 类型,PHP 中 abstract 类可以用 new static 后期静态绑定的方式实例化,而 create 方法里 $model = new static($attributes) 实际上就是重新实例化了并返回,而调用者 Model 类没有定义 table 属性,所以这个时候 $this->table 是没有值的。

图片描述

解决办法是用 save 方法即可,如图所示。实际上 create 方法也调用了 save 方法。

实验

一个抽象类 A,有个 create 方法,通过延迟静态绑定实例化并返回。B 类继承 A,test 方法中修改父类的 name 属性。

<?php
 
abstract class A
{
    protected $name = "tanteng";
 
    public static function create()
    {
        return new static();
    }
}
 
class B extends A
{
    //protected $name = '纸牌屋弗兰克';
 
    public function test()
    {
        $this->name = "Tony Tan";
        return $this;
    }
}
 
$obj1 = (new B)->test();
$obj2 = (new B)->test()->create();
var_dump($obj1);
var_dump($obj2);

结果显示 $obj1 和 $obj2 这两个实例都是 B 的实例,调用 test 方法属性 name 改变了,但是调用 create 方法后,name 属性并没有改变。这也就是在本文中说的在 Lavarel 中遇到的场景。(这里如果把注释打开,打印的 name 就是重写的值)

如果把抽象类 A 改成普通类,new static 改成 new self 的方式实例化,结果就不同了,打印的属性 name 都是各自类的属性。

相关文章:

  • 简单使用JSTL攻略
  • Powershell 编写和运行脚本
  • windos 下端口被占用
  • git与eclipse相关
  • 一个在ActionBar上显示图标和菜单PopupMenu的小示例(19)
  • 管理大数据:监测系统创造新的收益
  • 使用Jmeter创建ActiveMQ JMS POINT TO POINT请求
  • select 遇到的坑
  • iOS开发文件夹--Copy items if needed
  • SEO页面标题Title的优化
  • 优化函数式编程:向 PHP 移植 Clojure 函数
  • mxnet 源码阅读 7
  • ViewController之间的转场和数据传递
  • 基本数据结构:链表
  • LinuxMint17.3配置全局变量
  • AzureCon上微软宣布了哪些容器相关的重磅消息
  • canvas 五子棋游戏
  • k8s如何管理Pod
  • leetcode46 Permutation 排列组合
  • MQ框架的比较
  • node.js
  • overflow: hidden IE7无效
  • pdf文件如何在线转换为jpg图片
  • Python_OOP
  • Swoft 源码剖析 - 代码自动更新机制
  • 百度小程序遇到的问题
  • 得到一个数组中任意X个元素的所有组合 即C(n,m)
  • 系统认识JavaScript正则表达式
  • 在Mac OS X上安装 Ruby运行环境
  • 7行Python代码的人脸识别
  • Python 之网络式编程
  • 阿里云重庆大学大数据训练营落地分享
  • 关于Kubernetes Dashboard漏洞CVE-2018-18264的修复公告
  • ​如何使用ArcGIS Pro制作渐变河流效果
  • #QT(串口助手-界面)
  • #我与Java虚拟机的故事#连载02:“小蓝”陪伴的日日夜夜
  • (1)Android开发优化---------UI优化
  • (2)STM32单片机上位机
  • (floyd+补集) poj 3275
  • (二)PySpark3:SparkSQL编程
  • (附源码)php新闻发布平台 毕业设计 141646
  • (企业 / 公司项目)前端使用pingyin-pro将汉字转成拼音
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (四)Controller接口控制器详解(三)
  • (一)eclipse Dynamic web project 工程目录以及文件路径问题
  • (转载)OpenStack Hacker养成指南
  • .NET MVC之AOP
  • .NET Standard 的管理策略
  • .net 前台table如何加一列下拉框_如何用Word编辑参考文献
  • .NET 使用 ILMerge 合并多个程序集,避免引入额外的依赖
  • .NET建议使用的大小写命名原则
  • .NET设计模式(8):适配器模式(Adapter Pattern)
  • .Net下使用 Geb.Video.FFMPEG 操作视频文件
  • .one4-V-XXXXXXXX勒索病毒数据怎么处理|数据解密恢复
  • @manytomany 保存后数据被删除_[Windows] 数据恢复软件RStudio v8.14.179675 便携特别版...