摘要:实验一个抽象类,有个方法,通过延迟静态绑定实例化并返回。这里如果把注释打开,打印的就是重写的值如果把抽象类改成普通类,改成的方式实例化,结果就不同了,打印的属性都是各自类的属性。
(原文地址,内容以原文为准,可能修改或者补充: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 属性。
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 都是各自类的属性。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/25623.html
摘要:判断是否存在构造函数,不存在直接实例化,存在则通过来获取输入函数,并有相应的方法解决依赖参数问题,实现依赖注入。 Laravel 框架关键技术解析·读书笔记(一) 第一章 入口文件 请求访问的入口文件,主要完成几部分工作,分别是: 自动加载函数的添加 服务器实例化与服务注册 路由加载 请求实例化与路由分发 相应生成与发送 其中,自动加载函数用于包含引用文件,改文件是composer...
摘要:最近在维护一个三年前的旧代码,用的是框架。单元测试和语言并发控制实际上是个蛋疼的问题,夸张一点说,当时的并不能特别轻松地实现并发,甚至不能实现并发。语言的功能之一就是自带单元测试。用语言之前,我的习惯是不写单元测试。 最近在维护一个三年前的旧代码,用的是laravel框架。 从某些方面来讲,这个代码算是比较标准为了实现在规定的时间内完成相关功能,同时程序员水平不高、经过大量优化之后,变...
摘要:可以为服务提供者的方法设置类型提示。方法将在所有其他服务提供者均已注册之后调用。所有服务提供者都在配置文件中注册。可以选择推迟服务提供者的注册,直到真正需要注册绑定时,这样可以提供应用程序的性能。 本文最早发布于 Rootrl的Blog 导言 Laravel是一款先进的现代化框架,里面有一些概念非常重要。在上手Laravel之前,我认为先弄懂这些概念是很有必要的。你甚至需要重温下PHP...
摘要:的核心概念包括服务容器服务提供者门面契约。所有服务提供者都需要继承类。可以为服务提供者的方法设置类型提示。方法将在所有其他服务提供者均已注册之后调用。同样会整理成思维导图的形式以方便记忆与回顾。 showImg(https://segmentfault.com/img/remote/1460000010771201); Laravel 的核心概念包括:服务容器、服务提供者、门面(Fac...
摘要:服务提供者先看看定义服务提供者是所有应用程序启动的中心所在。通过本文,希望大家能够了解服务提供者,,和实际调用的类的实例之间的关系。 以 Laravel 自带的文件系统为例,在 config/app.php 的配置文件的 providers 数组中,注册了一个服务提供者: IlluminateFilesystemFilesystemServiceProvider::class, 在 a...
阅读 2904·2023-04-25 21:23
阅读 2996·2021-09-22 15:24
阅读 837·2019-08-30 12:55
阅读 2078·2019-08-29 18:42
阅读 2570·2019-08-29 16:27
阅读 886·2019-08-26 17:40
阅读 2154·2019-08-26 13:29
阅读 2584·2019-08-26 11:45