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中对xml读取的相关函数的介绍一
Jun 05 PHP
phpmyadmin 访问被拒绝的真实原因
Jun 15 PHP
使用VisualStudio开发php的图文设置方法
Aug 21 PHP
纯php打造的tab选项卡效果代码(不用js)
Dec 29 PHP
php输出表格的实现代码(修正版)
Dec 29 PHP
php设计模式 Observer(观察者模式)
Jun 26 PHP
ThinkPHP3.1新特性之对页面压缩输出的支持
Jun 19 PHP
[原创]PHP字符串中插入子字符串方法总结
May 06 PHP
深入讲解PHP的对象注入(Object Injection)
Mar 01 PHP
PHP unlink与rmdir删除目录及目录下所有文件实例代码
Feb 07 PHP
php模式设计之观察者模式应用实例分析
Sep 25 PHP
laravel框架数据库配置及操作数据库示例
Oct 10 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实现邮件发送并带有附件
2014/01/24 PHP
PHP的魔术常量__METHOD__简介
2014/07/08 PHP
非集成环境的php运行环境(Apache配置、Mysql)搭建安装图文教程
2016/04/12 PHP
php封装的smarty类完整实例
2016/10/19 PHP
jQuery textarea的长度进行验证
2009/05/06 Javascript
Web前端设计模式  制作漂亮的弹出层
2010/10/29 Javascript
页面装载js及性能分析方法介绍
2014/03/21 Javascript
[原创]Javascript 实现广告后加载 可加载百度谷歌联盟广告
2016/05/11 Javascript
javascript事件模型介绍
2016/05/31 Javascript
backbone简介_动力节点Java学院整理
2017/07/14 Javascript
Angular.js中$resource高大上的数据交互详解
2017/07/30 Javascript
详解A标签中href=&quot;&quot;的几种用法
2017/08/20 Javascript
Bootstrap一款超好用的前端框架
2017/09/25 Javascript
利用JS实现一个同Excel表现的智能填充算法
2018/08/13 Javascript
angularjs实现对表单输入改变的监控(ng-change和watch两种方式)
2018/08/29 Javascript
小程序获取周围IBeacon设备的方法
2018/10/31 Javascript
[02:16]DOTA2英雄基础教程 干扰者
2014/01/15 DOTA
Python中IPYTHON入门实例
2015/05/11 Python
python实现JAVA源代码从ANSI到UTF-8的批量转换方法
2015/08/10 Python
基于Python Shell获取hostname和fqdn释疑
2016/01/25 Python
python面向对象_详谈类的继承与方法的重载
2017/06/07 Python
OpenCV3.0+Python3.6实现特定颜色的物体追踪
2019/07/23 Python
Tensorflow的梯度异步更新示例
2020/01/23 Python
Python编程快速上手——疯狂填词程序实现方法分析
2020/02/29 Python
Python3将ipa包中的文件按大小排序
2020/04/17 Python
Python select及selectors模块概念用法详解
2020/06/22 Python
通过实例简单了解python yield使用方法
2020/08/06 Python
pandas数据分组groupby()和统计函数agg()的使用
2021/03/04 Python
css3之UI元素状态伪类选择器实例演示
2017/08/11 HTML / CSS
HTML5 placeholder属性详解
2016/06/22 HTML / CSS
贷款担保书范文
2014/05/13 职场文书
触电现场处置方案
2014/05/14 职场文书
个人整改措施落实情况汇报
2014/10/29 职场文书
导师工作推荐信
2015/03/27 职场文书
Nginx Rewrite使用场景及配置方法解析
2021/04/01 Servers
mysql 8.0.24版本安装配置方法图文教程
2021/05/12 MySQL