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环境套包 dedeampz 伪静态设置示例
Mar 26 PHP
PHP实现数字补零功能的2个函数介绍
May 12 PHP
windwos下使用php连接oracle数据库的过程分享
May 26 PHP
2个比较经典的PHP加密解密函数分享
Jul 01 PHP
PHP使用mysql_fetch_object从查询结果中获取对象集的方法
Mar 18 PHP
codeigniter实现get分页的方法
Jul 10 PHP
关于PHP开发的9条建议
Jul 27 PHP
PHP实现linux命令tail -f
Feb 22 PHP
php执行多个存储过程的方法【基于thinkPHP】
Nov 08 PHP
PHP验证终端类型是否为手机的简单实例
Feb 07 PHP
php如何利用pecl安装mongodb扩展详解
Jan 09 PHP
php设计模式之备忘模式分析【星际争霸游戏案例】
Mar 24 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中register_globals参数为OFF和ON的区别(register_globals 使用详解)
2012/02/05 PHP
ini_set的用法介绍
2014/01/07 PHP
php调整服务器时间的方法
2015/04/03 PHP
PHP实现获取中英文首字母
2015/06/19 PHP
简单谈谈php延迟静态绑定
2016/01/26 PHP
thinkPHP使用pclzip打包备份mysql数据库的方法
2016/04/30 PHP
php实现基于openssl的加密解密方法
2016/09/30 PHP
通过源码解析Laravel的依赖注入
2018/01/22 PHP
PHP实现登录验证码校验功能
2018/05/17 PHP
Array对象方法参考
2006/10/03 Javascript
几个javascript操作word的参考代码
2009/10/26 Javascript
Whatever:hover 无需javascript让IE支持丰富伪类
2010/06/29 Javascript
原生JS实现加入收藏夹的代码
2013/10/24 Javascript
JS测试显示屏分辨率以及屏幕尺寸的方法
2013/11/22 Javascript
24款热门实用的jQuery插件推荐
2014/12/24 Javascript
jQuery实现按钮点击遮罩加载及处理完后恢复的效果
2016/06/07 Javascript
浅谈javascript基础之客户端事件驱动
2016/06/10 Javascript
详解js的事件处理函数和动态创建html标记方法
2016/12/16 Javascript
js移动端事件基础及常用事件库详解
2017/08/15 Javascript
Node.js dgram模块实现UDP通信示例代码
2017/09/26 Javascript
JavaScript Canvas编写炫彩的网页时钟
2019/10/16 Javascript
vue实现五子棋游戏
2020/05/28 Javascript
解决Vue-cli无法编译es6的问题
2020/10/30 Javascript
python如何解析配置文件并应用到项目中
2019/06/27 Python
python有几个版本
2020/06/17 Python
python和php哪个更适合写爬虫
2020/06/22 Python
英国设计的甲板鞋和船鞋:Chatham
2018/12/06 全球购物
法学毕业生自我鉴定
2013/11/08 职场文书
化学教师教学反思
2014/01/17 职场文书
上课迟到检讨书
2014/01/19 职场文书
淘宝活动策划方案
2014/02/06 职场文书
法学函授自我鉴定
2014/02/06 职场文书
党员教师四风自我剖析材料
2014/09/30 职场文书
快速学习Oracle触发器和游标
2021/06/30 Oracle
vue3获取当前路由地址
2022/02/18 Vue.js
为Centos安装指定版本的Docker
2022/04/01 Servers