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函数)
Oct 09 PHP
thinkphp实现like模糊查询实例
Oct 29 PHP
分享PHP源码批量抓取远程网页图片并保存到本地的实现方法
Dec 01 PHP
php正则表达式验证(邮件地址、Url地址、电话号码、邮政编码)
Mar 14 PHP
详解Yii2 rules 的验证规则
Dec 02 PHP
ThinkPHP 整合Bootstrap Ajax分页样式
Dec 23 PHP
关于Laravel Route重定向的一个注意点
Jan 16 PHP
php使用gd2绘制基本图形示例(直线、圆、正方形)
Feb 15 PHP
PHP实现用户登录的案例代码
May 10 PHP
PHP快速导出百万级数据到CSV或者EXCEL文件
Nov 27 PHP
ThinkPHP5.1的权限控制怎么写?分享一个AUTH权限控制
Mar 09 PHP
phpquery中文手册
Mar 18 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
php自定义函数之递归删除文件及目录
2010/08/08 PHP
常用PHP框架功能对照表
2014/10/23 PHP
linux下实现定时执行php脚本
2015/02/13 PHP
php实现的任意进制互转类分享
2015/07/07 PHP
jquery文字上下滚动的实现方法
2013/03/22 Javascript
jquery全选/全不选/反选另一种实现方法(配合原生js)
2013/04/07 Javascript
JavaScript异步编程:异步数据收集的具体方法
2013/08/19 Javascript
Javascript中string转date示例代码
2013/11/01 Javascript
XMLHttpRequest处理xml格式的返回数据(示例代码)
2013/11/21 Javascript
js实现点击图片改变页面背景图的方法
2015/02/28 Javascript
jquery中checkbox使用方法简单实例演示
2015/11/24 Javascript
JS原型、原型链深入理解
2016/02/27 Javascript
js实现商品抛物线加入购物车特效
2020/11/18 Javascript
js实现加载更多功能实例
2016/10/27 Javascript
微信小程序实战之轮播图(3)
2017/04/17 Javascript
Node.js连接mongodb实例代码
2017/06/06 Javascript
JavaScript正则表达式校验与递归函数实际应用实例解析
2017/08/04 Javascript
webstorm中配置nodejs环境及npm的实例
2018/05/15 NodeJs
[52:07]完美世界DOTA2联赛PWL S3 LBZS vs access 第二场 12.10
2020/12/13 DOTA
python调用Moxa PCOMM Lite通过串口Ymodem协议实现发送文件
2014/08/15 Python
python里使用正则的findall函数的实例详解
2017/10/19 Python
Python多线程扫描端口代码示例
2018/02/09 Python
Flask框架 CSRF 保护实现方法详解
2019/10/30 Python
Jupyter打开图形界面并画出正弦函数图像实例
2020/04/24 Python
friso美素佳儿官方海外旗舰店:荷兰原产原罐
2017/07/03 全球购物
美国眼镜网:GlassesUSA
2017/09/07 全球购物
斯凯奇新西兰官网:SKECHERS新西兰
2018/02/22 全球购物
第二层交换机和路由器的区别?第三层交换机和路由器的区别?
2013/05/23 面试题
企业党建工作汇报材料
2014/08/19 职场文书
政协会议宣传标语
2014/10/09 职场文书
介绍信范文大全
2015/05/07 职场文书
坚持不是死撑,更重要的是心态
2019/08/19 职场文书
导游词之西江千户苗寨
2019/12/24 职场文书
vue如何批量引入组件、注册和使用详解
2021/05/12 Vue.js
python内置进制转换函数的操作
2021/06/02 Python
Win10/Win11 任务栏替换成经典样式
2022/04/19 数码科技