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 相关文章推荐
在Windows版的PHP中使用ADO
Oct 09 PHP
PHP针对JSON操作实例分析
Jan 12 PHP
PHP实现股票趋势图和柱形图
Feb 07 PHP
PHP 5.3和PHP 5.4出现FastCGI Error解决方法
Feb 12 PHP
如何使用jQuery+PHP+MySQL来实现一个在线测试项目
Apr 26 PHP
php随机显示指定文件夹下图片的方法
Jul 13 PHP
php简单统计中文个数的方法
Sep 30 PHP
php中preg_replace正则替换用法分析【一次替换多个值】
Jan 17 PHP
php二维码生成以及下载实现
Sep 28 PHP
总结PHP代码规范、流程规范、git规范
Jun 18 PHP
Yaf框架封装的MySQL数据库操作示例
Mar 06 PHP
php intval函数用法总结
Apr 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 修改zen-cart下单和付款流程以防止漏单
2010/03/08 PHP
php根据isbn书号查询amazon网站上的图书信息的示例
2014/02/13 PHP
thinkphp实现数组分页示例
2014/04/13 PHP
Yii分页用法实例详解
2014/12/04 PHP
php实现指定字符串中查找子字符串的方法
2015/03/17 PHP
laravel migrate初学常见错误的解决方法
2017/10/11 PHP
laravel model 两表联查示例
2019/10/24 PHP
AJAX 网页保留浏览器前进后退等功能
2011/02/12 Javascript
js控制再次点击按钮之间的间隔时间可防止重复提交
2014/08/01 Javascript
JavaScript代码因逗号不规范导致IE不兼容的问题
2016/02/25 Javascript
jquery实现无刷新验证码的简单实例
2016/05/19 Javascript
JS常用字符串方法(推荐)
2021/01/15 Javascript
js中window.open的参数及注意注意事项
2016/07/06 Javascript
JS实现将数字金额转换为大写人民币汉字的方法
2016/08/02 Javascript
AngularJS基础 ng-switch 指令简单示例
2016/08/03 Javascript
onmouseover事件和onmouseout事件全面理解
2016/08/15 Javascript
URL的参数中有加号传值变为空格的问题(URL特殊字符)
2016/11/04 Javascript
Vue.js实战之Vuex的入门教程
2017/04/01 Javascript
Bootstrap实现翻页效果
2017/11/27 Javascript
100行代码实现一个vue分页组功能
2018/11/06 Javascript
python批量修改文件名的实现代码
2014/09/01 Python
详解python的webrtc库实现语音端点检测
2017/05/31 Python
Python3.5内置模块之os模块、sys模块、shutil模块用法实例分析
2019/04/27 Python
Python 绘制酷炫的三维图步骤详解
2019/07/12 Python
Python识别快递条形码及Tesseract-OCR使用详解
2019/07/15 Python
基于Python安装pyecharts所遇的问题及解决方法
2019/08/12 Python
python运用pygame库实现双人弹球小游戏
2019/11/25 Python
python小项目之五子棋游戏
2019/12/26 Python
python绘制玫瑰的实现代码
2020/03/02 Python
Python使用pyyaml模块处理yaml数据
2020/04/14 Python
python re模块常见用法例举
2021/03/01 Python
优秀管理者事迹材料
2014/05/22 职场文书
先进员工事迹材料
2014/12/20 职场文书
抢劫罪辩护词
2015/05/21 职场文书
私人贷款担保书该怎么写呢?
2019/07/02 职场文书
SQL SERVER中常用日期函数的具体使用
2021/04/08 SQL Server