php反射学习之不用new方法实例化类操作示例


Posted in PHP onJune 14, 2019

本文实例讲述了php反射学习之不用new方法实例化类操作。分享给大家供大家参考,具体如下:

上一篇php反射入门示例简单介绍了 php 反射的几个常见类的使用方法,但是用反射能做些什么,你可能还是想象不到,

下面我稍微应用反射类来做点东西,大家知道实例化一个类需要用new 关键字,不用 new 可以吗?答案是可以的,用反射就能实现:

首先创建一个文件 student.php:

<?php
class Student
{
  public $id;
  public $name;
  public function __construct($id,$name)
  {
    $this->id = $id;
    $this->name = $name;
  }
  public function study()
  {
    echo $this->name.' is learning.....'.PHP_EOL;
  }
  public function showBag(){
    echo "My bag have ".$this->bag->all();
  }
}

另新建一个文件run.php

<?php
require 'student.php';
function make($class, $vars = []) {
  $ref = new ReflectionClass($class);
  if(!$ref->isInstantiable()) {
    throw new Exception("类{$class} 不存在");
  }
  $constructor = $ref->getConstructor();
  if(is_null($constructor)) {
    return new $class;
  }
  $params = $constructor->getParameters();
  $resolveParams = [];
  foreach ($params as $key=>$value) {
    $name = $value->getName();
    if(isset($vars[$name])) {
      $resolveParams[] = $vars[$name];
    } else {
      $default = $value->isDefaultValueAvailable() ? $value->getDefaultValue() : null;
      if(is_null($default)) {
        if($value->getClass()) {
          $resolveParams[] = make($value->getClass()->getName(), $vars);
        } else {
          throw new Exception("{$name} 没有传值且没有默认值。");
        }
      } else {
        $resolveParams[] = $default;
      }
    }
  }
  return $ref->newInstanceArgs($resolveParams);
}

run.php 中make 函数就是我们用来实例化类而编写的函数,第一个参数传入类名,第二个参数是类的构造函数需要传入的参数数据。

根据 Student 的构造函数的参数不同有几种情况:(以下代码,请按不同情况追加到 run.php 中运行)

情况一: 没有提供 $name 的值

try {
  $stu = make('Student', ['id' => 1]);
  print_r($stu);
  $stu->study();
} catch (Exception $e) {
  echo $e->getMessage();
}

在构造函数中$name 没有默认值时,情况一会报错, 你可以稍微修改下 Student类,给 $name 提供一个默认值,这时候就不会报错了。

情况二 提供了 $name 的值

try {
  $stu = make('Student', ['id' => 1, 'name' => 'li']);
  print_r($stu);
  $stu->study();
} catch (Exception $e) {
  echo $e->getMessage();
}

情况三,我们把 student.php 改一下

<?php
class Bag{
  public function name(){
    return "学生包".PHP_EOL;
  }
}
class Student
{
  public $id;
  public $name;
  public function __construct($id, $name="xxx", Bag $bag)
  {
    $this->id = $id;
    $this->name = $name;
    $this->bag = $bag;
  }
  public function study()
  {
    echo $this->name.' is learning.....'.PHP_EOL;
  }
  public function showBag(){
    echo "My bag is ".$this->bag->name();
  }
}

可以看到,给 Student 类加了一个参数$bag, 类型 是 Bag

这时候运行一下

<?php
try {
  $stu = make('Student', ['id' => 1, 'name' => 'li']);
  print_r($stu);
  $stu->study();
  $stu->showBag();
} catch (Exception $e) {
  echo $e->getMessage();
}

可以看到构造函数的第三个参数 $bag ,被自动实例化了,然后传递给了 Student 类的构造函数,这个部分很关键,这个地方可以用来实现依赖注入,我们不必在手动实例化对象了,我们可以根据参数的对应的类来自动实例化对象,从而实现类之间的解耦。如果你学过 Laravel的话,你应该对这个很熟悉了。

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
php下保存远程图片到本地的办法
Aug 08 PHP
PHP中遍历stdclass object的实现代码
Jun 09 PHP
PHP 文件系统详解
Sep 13 PHP
PHP实现HTML生成PDF文件的方法
Nov 07 PHP
ThinkPHP模板输出display用法分析
Nov 26 PHP
PHP使用适合阅读的格式显示文件大小的方法
Mar 05 PHP
php显示指定目录下子目录的方法
Mar 20 PHP
Yii2增加验证码步骤详解
Apr 25 PHP
JSON两种结构之对象和数组的理解
Jul 19 PHP
php的laravel框架快速集成微信登录的方法
Dec 12 PHP
PHP中Notice错误常见解决方法
Apr 28 PHP
PHP中递归的实现实例详解
Nov 14 PHP
PHP反射学习入门示例
Jun 14 #PHP
PHP如何实现阿里云短信sdk灵活应用在项目中的方法
Jun 14 #PHP
PHP中常用的三种设计模式详解【单例模式、工厂模式、观察者模式】
Jun 14 #PHP
PHP面向对象程序设计子类扩展父类(子类重新载入父类)操作详解
Jun 14 #PHP
PHP面向对象程序设计模拟一般面向对象语言中的方法重载(overload)示例
Jun 13 #PHP
PHP面向对象程序设计重载(overloading)操作详解
Jun 13 #PHP
PHP面向对象程序设计之构造方法和析构方法详解
Jun 13 #PHP
You might like
Oracle Faq(Oracle的版本)
2006/10/09 PHP
基于在生产环境中使用php性能测试工具xhprof的详解
2013/06/03 PHP
php批量上传的实现代码
2013/06/09 PHP
Laravel学习教程之IOC容器的介绍与用例
2017/08/15 PHP
jQuery 性能优化指南(2)
2009/05/21 Javascript
JavaScript 学习笔记之语句
2015/01/14 Javascript
js获取及判断键盘按键的方法
2015/12/01 Javascript
jQuery版本升级踩坑大全
2016/01/12 Javascript
基于Jquery和html5实现炫酷的3D焦点图动画
2016/03/02 Javascript
在JavaScript中模拟类(class)及类的继承关系
2016/05/20 Javascript
AngularJs IE Compatibility 兼容老版本IE
2016/09/01 Javascript
基于JS实现发送短信验证码后的倒计时功能(无视页面刷新,页面关闭不进行倒计时功能)
2016/09/02 Javascript
微信小程序 rpx 尺寸单位详细介绍
2016/10/13 Javascript
jQuery实现的小图列表,大图展示效果幻灯片示例
2016/10/25 Javascript
JS简单实现动态添加HTML标记的方法示例
2018/04/08 Javascript
Vue2.0 实现移动端图片上传功能
2018/05/30 Javascript
Vue Cli 3项目使用融云IM实现聊天功能的方法
2019/04/19 Javascript
vue解决使用$http获取数据时报错的问题
2019/10/30 Javascript
tensorflow实现二维平面模拟三维数据教程
2020/02/11 Python
Python响应对象text属性乱码解决方案
2020/03/31 Python
CentOS 7如何实现定时执行python脚本
2020/06/24 Python
详解如何在pyqt中通过OpenCV实现对窗口的透视变换
2020/09/20 Python
python中watchdog文件监控与检测上传功能
2020/10/30 Python
解决python的空格和tab混淆而报错的问题
2021/02/26 Python
欧洲领先的技术商店:eibmarkt.com
2019/05/10 全球购物
N:Philanthropy官网:美国洛杉矶基础款服装
2020/06/09 全球购物
大学毕业感言
2014/01/10 职场文书
面试后感谢信怎么写
2014/02/01 职场文书
材料加工工程求职信
2014/02/19 职场文书
面试自我介绍演讲稿
2014/04/29 职场文书
宣传普通话标语
2014/06/27 职场文书
迎国庆演讲稿
2014/09/15 职场文书
镇党委书记群众路线整改措施思想汇报
2014/10/13 职场文书
应聘教师求职信范文
2015/03/20 职场文书
钱学森电影观后感
2015/06/04 职场文书
Python django中如何使用restful框架
2021/06/23 Python