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 相关文章推荐
同时提取多条新闻中的文本一例
Oct 09 PHP
php中的观察者模式
Mar 24 PHP
关于session在PHP5的配置文件中的详细设置参数说明
Apr 20 PHP
php下载文件的代码示例
Jun 29 PHP
PHP将XML转数组过程详解
Nov 13 PHP
php页码形式分页函数支持静态化地址及ajax分页
Mar 28 PHP
深入理解PHP内核(二)之SAPI探究
Nov 10 PHP
Discuz论坛密码与密保加密规则
Dec 19 PHP
完美解决php 导出excle的.csv格式的数据时乱码问题
Feb 18 PHP
PHP实现的回溯算法示例
Aug 15 PHP
对于Laravel 5.5核心架构的深入理解
Feb 22 PHP
php中的依赖注入实例详解
Aug 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
用PHP书写安全的脚本代码
2012/02/05 PHP
使用phpQuery采集网页的方法
2013/11/13 PHP
PHP版本如何选择?应该使用哪个版本?
2015/05/13 PHP
PHP实现与java 通信的插件使用教程
2019/08/11 PHP
javascript笔记 String类replace函数的一些事
2011/09/22 Javascript
正则表达式搭配js轻松处理json文本方便而老古
2013/02/17 Javascript
jQuery中$.fn的用法示例介绍
2013/11/05 Javascript
javascript实现数字+字母验证码的简单实例
2014/02/10 Javascript
浅析Node在构建超媒体API中的作用
2014/07/30 Javascript
微信内置浏览器私有接口WeixinJSBridge介绍
2015/05/25 Javascript
使用JavaScript实现连续滚动字幕效果的方法
2015/07/07 Javascript
Jquery easyui 实现动态树
2015/11/17 Javascript
javascript事件模型介绍
2016/05/31 Javascript
JS动态给对象添加事件的简单方法
2016/07/19 Javascript
jquery控制页面的展开和隐藏实现方法(推荐)
2016/10/15 Javascript
jQuery实现checkbox列表的全选、反选功能
2016/11/24 Javascript
解决bootstrap模态框数据缓存的问题方法
2018/08/10 Javascript
使用JavaScript获取扫码枪扫描得到的条形码的思路代码详解
2020/06/10 Javascript
Antd的Table组件嵌套Table以及选择框联动操作
2020/10/24 Javascript
Python 装饰器深入理解
2017/03/16 Python
pandas object格式转float64格式的方法
2018/04/10 Python
pycharm恢复默认设置或者是替换pycharm的解释器实例
2018/10/29 Python
Python实现屏幕录制功能的代码
2020/03/02 Python
PageFactory设计模式基于python实现
2020/04/14 Python
Python tkinter界面实现历史天气查询的示例代码
2020/08/23 Python
澳大利亚购买最佳炊具品牌网站:Cookware Brands
2019/02/16 全球购物
运动会领导邀请函
2014/02/05 职场文书
乡村卫生服务一体化管理实施方案
2014/03/30 职场文书
银行求职自荐信
2014/06/30 职场文书
大学生军训自我鉴定范文
2014/09/18 职场文书
投标售后服务承诺书
2015/04/29 职场文书
奥巴马开学演讲观后感
2015/06/12 职场文书
爱国教育主题班会
2015/08/14 职场文书
PHP使用QR Code生成二维码实例
2021/07/07 PHP
【海涛教你打dota】体验一超神发条:咱是抢盾专业户
2022/04/01 DOTA
利用 Python 的 Pandas和 NumPy 库来清理数据
2022/04/13 Python