当前位置: 首页 > 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配置全局变量
  • 【347天】每日项目总结系列085(2018.01.18)
  • Android Volley源码解析
  • extjs4学习之配置
  • laravel5.5 视图共享数据
  • mysql 5.6 原生Online DDL解析
  • node入门
  • SpingCloudBus整合RabbitMQ
  • Theano - 导数
  • vue:响应原理
  • Vue--数据传输
  • 从tcpdump抓包看TCP/IP协议
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 分布式事物理论与实践
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 力扣(LeetCode)357
  • 前端每日实战:61# 视频演示如何用纯 CSS 创作一只咖啡壶
  • 数据可视化之 Sankey 桑基图的实现
  • 走向全栈之MongoDB的使用
  • media数据库操作,可以进行增删改查,实现回收站,隐私照片功能 SharedPreferences存储地址:
  • Mac 上flink的安装与启动
  • ​secrets --- 生成管理密码的安全随机数​
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • (BFS)hdoj2377-Bus Pass
  • (done) NLP “bag-of-words“ 方法 (带有二元分类和多元分类两个例子)词袋模型、BoW
  • (笔记)Kotlin——Android封装ViewBinding之二 优化
  • (二十三)Flask之高频面试点
  • (附源码)springboot教学评价 毕业设计 641310
  • (一)python发送HTTP 请求的两种方式(get和post )
  • (一)为什么要选择C++
  • (原創) 人會胖會瘦,都是自我要求的結果 (日記)
  • (转)Oracle 9i 数据库设计指引全集(1)
  • (转)创业家杂志:UCWEB天使第一步
  • .net 4.0 A potentially dangerous Request.Form value was detected from the client 的解决方案
  • .net 获取url的方法
  • .net 生成二级域名
  • .net6Api后台+uniapp导出Excel
  • .Net6使用WebSocket与前端进行通信
  • .NET开源全面方便的第三方登录组件集合 - MrHuo.OAuth
  • [ Linux 长征路第二篇] 基本指令head,tail,date,cal,find,grep,zip,tar,bc,unname
  • [<死锁专题>]