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在线生成ico文件的代码
Oct 09 PHP
浅谈PHP中单引号和双引号到底有啥区别呢?
Mar 04 PHP
php抓取网站图片并保存的实现方法
Oct 29 PHP
实例简介PHP的一些高级面向对象编程的特性
Nov 27 PHP
Linux下编译redis和phpredis的方法
Apr 07 PHP
ThinkPHP框架实现的邮箱激活功能示例
Jun 15 PHP
Laravel框架实现的rbac权限管理操作示例
Jan 16 PHP
PHP实现字符串的全排列详解
Apr 24 PHP
PHP实现的62进制转10进制,10进制转62进制函数示例
Jun 06 PHP
thinkPHP框架乐观锁和悲观锁实例分析
Oct 30 PHP
php经典趣味算法实例代码
Jan 21 PHP
Laravel统一错误处理为JSON的方法介绍
Oct 18 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
sony ICF-2010 拆解与改装
2021/03/02 无线电
php 信息采集程序代码
2009/03/17 PHP
PHP Zip解压 文件在线解压缩的函数代码
2010/05/26 PHP
PHP常用的三种设计模式汇总
2016/08/28 PHP
PHP 实现人民币小写转换成大写的方法及大小写转换函数
2017/11/17 PHP
Aster vs Newbee BO3 第三场2.18
2021/03/10 DOTA
IE6下js通过css隐藏select的一个bug
2010/08/16 Javascript
让浏览器非阻塞加载javascript的几种方法小结
2011/04/25 Javascript
jQuery实现用户注册的表单验证示例
2013/08/28 Javascript
在点击div中的p时,如何阻止事件冒泡
2017/02/07 Javascript
vue+vuex+axios+echarts画一个动态更新的中国地图的方法
2017/12/19 Javascript
使用vue官方提供的模板vue-cli搭建一个helloWorld案例分析
2018/01/16 Javascript
vuejs中监听窗口关闭和窗口刷新事件的方法
2018/09/21 Javascript
利用Vue构造器创建Form组件的通用解决方法
2018/12/03 Javascript
Vue实现数据请求拦截
2019/10/23 Javascript
[02:49]DAC2018决赛日TOP5 LGD开启黑暗之门绝杀VP
2018/04/08 DOTA
[40:31]Secret vs Alliacne 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
python实现飞机大战游戏
2020/10/26 Python
pyqt5 实现多窗口跳转的方法
2019/06/19 Python
python3实现微型的web服务器
2019/09/03 Python
python实现横向拼接图片
2020/03/23 Python
python中format函数如何使用
2020/06/22 Python
python 19个值得学习的编程技巧
2020/08/15 Python
Html5插件教程之添加浏览器放大镜效果的商品橱窗
2016/01/07 HTML / CSS
英国最红的高街时尚品牌:Topshop
2016/08/05 全球购物
阿里健康官方海外旗舰店:阿里健康国际自营
2017/11/24 全球购物
Club Monaco加拿大官网:设计师男女服装
2019/09/29 全球购物
销售类个人求职信范文
2013/09/25 职场文书
生产经理的自我评价分享
2013/11/07 职场文书
大学生暑期实践感言
2014/02/26 职场文书
安全环保标语
2014/06/09 职场文书
结婚保证书
2015/01/16 职场文书
邀请函格式范文
2015/02/02 职场文书
大明湖导游词
2015/02/03 职场文书
pytorch 中nn.Dropout的使用说明
2021/05/20 Python
MySQL中datetime时间字段的四舍五入操作
2021/10/05 MySQL