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 imagecreatefrombmp 从BMP文件或URL新建一图像
Jul 16 PHP
ThinkPHP模板中数组循环实例
Oct 30 PHP
ThinkPHP在新浪SAE平台的部署实例
Oct 31 PHP
php自定义urlencode,urldecode函数实例
Mar 24 PHP
PHP使用pear自带的mail类库发邮件的方法
Jul 08 PHP
php 使用curl模拟登录人人(校内)网的简单实例
Jun 06 PHP
yii2.0整合阿里云oss删除单个文件的方法
Sep 19 PHP
在 Laravel 中 “规范” 的开发短信验证码发送功能
Oct 26 PHP
PHP设计模式之原型设计模式原理与用法分析
Apr 25 PHP
PHP PDOStatement::fetchAll讲解
Jan 31 PHP
利用PHP内置SERVER开启web服务(本地开发使用)
Jan 22 PHP
php+mysql实现的无限分类方法类定义与使用示例
May 27 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
Notice: Undefined index: page in E:\PHP\test.php on line 14
2010/11/02 PHP
php实现邮件发送并带有附件
2014/01/24 PHP
ecshop实现smtp发送邮件
2015/02/03 PHP
Smarty foreach控制循环次数的一些方法
2015/07/01 PHP
PHP加密3DES报错 Call to undefined function: mcrypt_module_open() 如何解决
2016/04/17 PHP
Thinkphp5 自定义上传文件名的实现方法
2019/07/23 PHP
PhpStorm 如何优雅的调试Hyperf的方法步骤
2019/11/24 PHP
JavaScript 应用类库代码
2008/06/02 Javascript
jQuery调用AJAX时Get和post公用的乱码解决方法实例说明
2013/06/04 Javascript
JavaScript动态操作表格实例(添加,删除行,列及单元格)
2013/11/25 Javascript
javascript设置金额样式转换保留两位小数示例代码
2013/12/04 Javascript
webpack配置文件和常用配置项介绍
2017/04/28 Javascript
详解react-router4 异步加载路由两种方法
2017/09/12 Javascript
ES6 javascript中class类的get与set用法实例分析
2017/10/30 Javascript
JS在if中的强制类型转换方式
2018/07/15 Javascript
解决vue-cli项目webpack打包后iconfont文件路径的问题
2018/09/01 Javascript
详解vue如何使用rules对表单字段进行校验
2018/10/17 Javascript
微信小程序实现选择地址省市区三级联动
2020/06/21 Javascript
vue a标签点击实现赋值方式
2020/09/07 Javascript
Vue切换Tab动态渲染组件的操作
2020/09/21 Javascript
[55:25]2018DOTA2亚洲邀请赛3月29日 小组赛A组 VG VS OG
2018/03/30 DOTA
运用Python的webbrowser实现定时打开特定网页
2019/02/21 Python
用Python写一个模拟qq聊天小程序的代码实例
2019/03/06 Python
python3常用的数据清洗方法(小结)
2019/10/31 Python
pytorch进行上采样的种类实例
2020/02/18 Python
Python基础之列表常见操作经典实例详解
2020/02/26 Python
python 已知一个字符,在一个list中找出近似值或相似值实现模糊匹配
2020/02/29 Python
python 用opencv实现霍夫线变换
2020/11/27 Python
HTML5实现移动端复制功能
2018/04/19 HTML / CSS
小学教师培训感言
2014/02/11 职场文书
创文明城市标语
2014/06/16 职场文书
创建绿色社区汇报材料
2014/08/22 职场文书
委托证明书
2014/09/17 职场文书
基层领导干部“四风”问题批评与自我批评
2014/09/23 职场文书
2015年纪委工作总结
2015/05/13 职场文书
安全生产会议制度
2015/08/06 职场文书