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 相关文章推荐
杏林同学录(七)
Oct 09 PHP
一些 PHP 管理系统程序中的后门
Aug 05 PHP
PHP curl 并发最佳实践代码分享
Sep 05 PHP
PHP输入流php://input介绍
Sep 18 PHP
php将mysql数据库整库导出生成sql文件的具体实现
Jan 08 PHP
通过dbi使用perl连接mysql数据库的方法
Apr 16 PHP
php数组操作之键名比较与差集、交集赋值的方法
Nov 10 PHP
php强制运行广告的方法
Dec 01 PHP
PHP中使用Imagick操作PSD文件实例
Jan 26 PHP
php从给定url获取文件扩展名的方法
Mar 14 PHP
Netbeans 8.2与PHP相关的新特性介绍
Oct 08 PHP
PHP simplexml_load_file()函数讲解
Feb 03 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 split汉字
2009/06/05 PHP
php面向对象全攻略 (九)访问类型
2009/09/30 PHP
浅析PHP递归函数返回值使用方法
2013/02/18 PHP
推荐10个提供免费PHP脚本下载的网站
2014/12/31 PHP
php删除文本文件中重复行的方法
2015/04/28 PHP
php中使用gd库实现远程图片下载实例
2015/05/12 PHP
php判断数组是否为空的实例方法
2020/05/10 PHP
Use Word to Search for Files
2007/06/15 Javascript
自动设置iframe大小的jQuery代码
2013/09/11 Javascript
使用jQuery设置disabled属性与移除disabled属性
2014/08/21 Javascript
AngularJS入门教程(二):AngularJS模板
2014/12/06 Javascript
深入理解JavaScript编程中的同步与异步机制
2015/06/24 Javascript
分享JavaScript监听全部Ajax请求事件的方法
2016/08/28 Javascript
jQuery用noConflict代替$的实现方法
2017/04/12 jQuery
webpack分离css单独打包的方法
2018/06/12 Javascript
js jquery 获取某一元素到浏览器顶端的距离实现方法
2018/09/05 jQuery
支付宝小程序实现省市区三级联动
2020/06/21 Javascript
jquery简易手风琴插件的封装
2020/10/13 jQuery
[03:08]TI9战队档案 - Vici Gaming
2019/08/20 DOTA
python2.7到3.x迁移指南
2018/02/01 Python
Python 实现12306登录功能实例代码
2018/02/09 Python
Python使用xlwt模块操作Excel的方法详解
2018/03/27 Python
基于python绘制科赫雪花
2018/06/22 Python
python变量赋值方法(可变与不可变)
2019/01/12 Python
python读取指定字节长度的文本方法
2019/08/27 Python
pymysql 插入数据 转义处理方式
2020/03/02 Python
解决json中ensure_ascii=False的问题
2020/04/03 Python
Python新手如何理解循环加载模块
2020/05/29 Python
python 使用xlsxwriter循环向excel中插入数据和图片的操作
2021/01/01 Python
英国领先的独立时装店:Van Mildert
2019/10/28 全球购物
贵阳市党的群众路线教育实践活动党(工)委领导班子整改方案
2014/10/26 职场文书
2015年乡镇扶贫工作总结
2015/04/08 职场文书
送达通知书
2015/04/25 职场文书
社区禁毒宣传活动总结
2015/05/07 职场文书
2021年最新用于图像处理的Python库总结
2021/06/15 Python
mysql 索引的数据结构为什么要采用B+树
2022/04/26 MySQL