laravel框架模型中非静态方法也能静态调用的原理分析


Posted in PHP onNovember 23, 2019

本文实例讲述了laravel框架模型中非静态方法也能静态调用的原理.分享给大家供大家参考,具体如下:

刚开始用laravel模型时,为了方便一直写静态方法,进行数据库操作。

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
  public static function getList()
  {
    return self::get()->toArray();
  }
}

直到有朋友告诉可以不用这么写,声明一个 protected 方法,方法中用 $this。在外部使用时,也可以像调静态函数一样调用。

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
  protected function getList()
  {
    return $this->get()->toArray();
  }
}

试了一下,发现还真可以,按理说受保护的 protected 非静态方法,在外部是无法这么调用的 User::getList() 。

但是在 laravel 中就可以,查看了下 Model 基类的代码,原来是因为实现了 __call() 和 __callStatic() 这两个魔术方法。

class Model
{
  public function __call($method, $parameters)
  {
    if (in_array($method, ['increment', 'decrement'])) {
      return $this->$method(...$parameters);
    }
    return $this->forwardCallTo($this->newQuery(), $method, $parameters);
  }
  public static function __callStatic($method, $parameters)
  {
    return (new static)->$method(...$parameters);
  }
}

我们试着自已实现下这两个魔术方法,看看效果。

<?php
namespace App\Models;
class Model
{
  //在对象中调用一个不可访问方法时,__call()被调用
  public function __call($method, $parameters)
  {
    echo '__call()';
    return $this->{$method}(...$parameters);
  }
  //在静态上下文中调用一个不可访问方法时,__callStatic()被调用
  public static function __callStatic($method, $parameters)
  {
    echo '__callStatic()';
    //注意这里,通过延迟静态绑定,仍然new了一个实例
    return (new static)->{$method}(...$parameters);
  }
  private function test()
  {
    echo '被调用了<br>';
  }
}

我们尝试调用 test() 方法。

<?php
namespace App\Http\Controllers\Test;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Model;
class Test extends Controller
{
  public function index(Request $request)
  {
    //对象调用
    (new Model())->test();
    //静态方法调用
    Model::test();
  }
}

结果显示调用成功。

希望本文所述对大家基于Laravel框架的PHP程序设计有所帮助。

PHP 相关文章推荐
PHP分页显示制作详细讲解
Dec 05 PHP
php部分常见问题总结
Mar 27 PHP
PHP获取文件后缀名的三个函数
Oct 15 PHP
php 无法加载mcrypt.dll的解决办法
Apr 03 PHP
简单的php数据库操作类代码(增,删,改,查)
Apr 08 PHP
解决ThinkPHP关闭调试模式时报错的问题汇总
Apr 22 PHP
PHP GD库相关图像生成和处理函数小结
Sep 30 PHP
thinkPHP实现的省市区三级联动功能示例
May 05 PHP
PHP实现QQ登录的开原理和实现过程
Feb 04 PHP
PHP中实现中文字串截取无乱码的解决方法
May 29 PHP
PHP进阶学习之Geo的地图定位算法详解
Jun 19 PHP
jQuery+PHP实现图片上传并提交功能
Jul 27 PHP
laravel框架中路由设置,路由参数和路由命名实例分析
Nov 23 #PHP
laravel框架创建授权策略实例分析
Nov 22 #PHP
laravel框架语言包拓展实现方法分析
Nov 22 #PHP
laravel框架邮箱认证实现方法详解
Nov 22 #PHP
laravel 框架结合关联查询 when()用法分析
Nov 22 #PHP
PHP实现微信提现功能(微信商城)
Nov 21 #PHP
使用PHP+Redis实现延迟任务,实现自动取消订单功能
Nov 21 #PHP
You might like
php性能优化分析工具XDebug 大型网站调试工具
2011/05/22 PHP
解析phpstorm + xdebug 远程断点调试
2013/06/20 PHP
thinkPHP订单数字提醒功能的实现方法
2016/12/01 PHP
PHP实现动态获取函数参数的方法示例
2018/04/02 PHP
JavaScript 对象、函数和继承
2009/07/07 Javascript
显示js对象所有属性和方法的函数
2009/10/16 Javascript
JavaScript 10件让人费解的事情
2010/02/15 Javascript
页面载入结束自动调用js函数示例
2013/09/23 Javascript
Jquery中的层次选择器与find()的区别示例介绍
2014/02/20 Javascript
jquery实现的鼠标下拉滚动置顶效果
2014/07/24 Javascript
JS 打印功能代码可实现打印预览、打印设置等
2014/10/31 Javascript
分享2个jQuery插件--jquery.fileupload与artdialog
2014/12/26 Javascript
常用的JavaScript模板引擎介绍
2015/02/28 Javascript
实现音乐播放器的代码(html5+css3+jquery)
2015/08/04 Javascript
vue.js入门教程之计算属性
2016/09/01 Javascript
第一次接触神奇的Bootstrap
2016/10/14 Javascript
React应用中使用Bootstrap的方法
2017/08/15 Javascript
vue兄弟组件传递数据的实例
2018/09/06 Javascript
vue ssr 实现方式(学习笔记)
2019/01/18 Javascript
Vue CLI3创建项目部署到Tomcat 使用ngrok映射到外网
2019/05/16 Javascript
使用kbone解决Vue项目同时支持小程序问题
2019/11/08 Javascript
python操作CouchDB的方法
2014/10/08 Python
基于Python3 逗号代码 和 字符图网格(详谈)
2017/06/22 Python
Python + selenium自动化环境搭建的完整步骤
2018/05/19 Python
python numpy 显示图像阵列的实例
2018/07/02 Python
pyinstaller打包多个py文件和去除cmd黑框的方法
2019/06/21 Python
Python3 文章标题关键字提取的例子
2019/08/26 Python
pytorch-神经网络拟合曲线实例
2020/01/15 Python
python计算二维矩形IOU实例
2020/01/18 Python
PyCharm2020.1.2社区版安装,配置及使用教程详解(Windows)
2020/08/07 Python
使用Python Tkinter实现剪刀石头布小游戏功能
2020/10/23 Python
全球速卖通巴西站点:Aliexpress巴西
2016/08/24 全球购物
应届毕业生应聘自荐信范文
2014/02/26 职场文书
年度优秀员工获奖感言
2014/08/15 职场文书
2016教师读书思廉心得体会
2016/01/23 职场文书
redis lua限流算法实现示例
2022/07/15 Redis