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 相关文章推荐
第五节--克隆
Nov 16 PHP
php代码运行时间查看类代码分享
Aug 06 PHP
Sorting Array Values in PHP(数组排序)
Sep 15 PHP
Laravel5中contracts详解
Mar 02 PHP
php实现图片上传、剪切功能
May 07 PHP
PHP下载文件的函数实例代码
May 18 PHP
基于PHPexecl类生成复杂的报表表头示例
Oct 14 PHP
PHP读取zip文件的方法示例
Nov 17 PHP
yii2-GridView在开发中常用的功能及技巧总结
Jan 07 PHP
[原创]php使用strpos判断字符串中数字类型子字符串出错的解决方法
Apr 01 PHP
PHP实现登录验证码校验功能
May 17 PHP
PHP中strtr与str_replace函数运行性能简单测试示例
Jun 22 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
让你同时上传 1000 个文件 (二)
2006/10/09 PHP
php calender(日历)二个版本代码示例(解决2038问题)
2013/12/24 PHP
PHP利用Socket获取网站的SSL证书与公钥
2017/06/18 PHP
Laravel框架使用Seeder实现自动填充数据功能
2018/06/13 PHP
jQuery Study Notes学习笔记 (二)
2010/08/04 Javascript
javaScript 删除字符串空格多种方法小结
2012/10/24 Javascript
fancybox modal的完美解决(右上的X)
2012/10/30 Javascript
jquery触发a标签跳转事件示例代码
2013/07/21 Javascript
js实现类似于add(1)(2)(3)调用方式的方法
2015/03/04 Javascript
Javascript函数式编程语言
2015/10/11 Javascript
基于BootStrap Metronic开发框架经验小结【六】对话框及提示框的处理和优化
2016/05/12 Javascript
功能强大的Bootstrap组件(结合js)
2016/08/03 Javascript
深入理解bootstrap框架之第二章整体架构
2016/10/09 Javascript
JS中页面与页面之间超链接跳转中文乱码问题的解决办法
2016/12/15 Javascript
javascript解析ajax返回的xml和json格式数据实例详解
2017/01/05 Javascript
纯JS实现弹性导航条效果
2017/03/06 Javascript
javascript 中的继承实例详解
2017/05/05 Javascript
D3.js的基础部分之数组的处理数组的排序和求值(v3版本)
2019/05/09 Javascript
微信小程序如何再次获取用户授权的方法
2019/05/10 Javascript
uni-app实现点赞评论功能
2019/11/25 Javascript
jQuery实现雪花飘落效果
2020/08/02 jQuery
js观察者模式的弹幕案例
2020/11/23 Javascript
vuex的使用步骤
2021/01/06 Vue.js
Python内存管理方式和垃圾回收算法解析
2017/11/11 Python
Python中Numpy mat的使用详解
2019/05/24 Python
解决python xx.py文件点击完之后一闪而过的问题
2019/06/24 Python
Python企业编码生成系统之主程序模块设计详解
2019/07/26 Python
pygame实现俄罗斯方块游戏(基础篇2)
2019/10/29 Python
互动出版网:专业书籍
2017/03/21 全球购物
linux面试题参考答案(10)
2013/11/04 面试题
农村优秀教师事迹材料
2014/08/27 职场文书
员工自我评价范文
2015/03/11 职场文书
电影焦裕禄观后感
2015/06/09 职场文书
尊师重教主题班会
2015/08/14 职场文书
小学大队干部竞选稿
2015/11/20 职场文书
Python学习之包与模块详解
2022/03/19 Python