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 缓存函数代码
Aug 27 PHP
curl不使用文件存取cookie php使用curl获取cookie示例
Jan 26 PHP
phpphp图片采集后按原路径保存图片示例
Feb 18 PHP
ThinkPHP中Session用法详解
Nov 29 PHP
php中Socket创建与监听实现方法
Jan 05 PHP
php写入数据到CSV文件的方法
Mar 14 PHP
Zend Framework教程之Loader以及PluginLoader用法详解
Mar 09 PHP
php数组分页实现方法
Apr 30 PHP
PHP正则匹配反斜杠'\'和美元'$'的方法
Feb 08 PHP
PHP开发实现快递查询功能详解
Apr 08 PHP
基于PHP实现短信验证码发送次数限制
Jul 11 PHP
php实例化对象的实例方法
Nov 17 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
全国FM电台频率大全 - 3 河北省
2020/03/11 无线电
mysq GBKl乱码
2006/11/28 PHP
php入门学习知识点一 PHP与MYSql连接与查询
2011/07/14 PHP
PHP笔记之:基于面向对象设计的详解
2013/05/14 PHP
基于PHP后台的Android新闻浏览客户端
2016/05/23 PHP
PHP微信开发之文本自动回复
2016/06/23 PHP
PHP中字符串长度的截取用法示例
2017/01/12 PHP
ThinkPHP3.2框架自定义配置和加载用法示例
2018/06/14 PHP
JavaScript基础篇之变量作用域、传值、传址的简单介绍与实例
2013/06/29 Javascript
jquery插件冲突(jquery.noconflict)解决方法分享
2014/03/20 Javascript
javascript浏览器窗口之间传递数据的方法
2015/01/20 Javascript
jQuery找出网页上最高元素的方法
2015/03/20 Javascript
jQuery简单实现QQ空间点赞已经取消点赞
2015/04/02 Javascript
javascript新闻跑马灯实例代码
2020/07/29 Javascript
Javascript实现图片轮播效果(二)图片序列节点的控制实现
2016/02/17 Javascript
微信小程序简单实现form表单获取输入数据功能示例
2017/11/30 Javascript
微信小程序云开发(数据库)详解
2019/05/17 Javascript
Vue 实现简易多行滚动&quot;弹幕&quot;效果
2020/01/02 Javascript
[02:23]2016国际邀请赛中国区预选赛wings晋级之路
2016/06/29 DOTA
Python接收Gmail新邮件并发送到gtalk的方法
2015/03/10 Python
python远程连接服务器MySQL数据库
2018/07/02 Python
解决python线程卡死的问题
2019/02/18 Python
Python提取转移文件夹内所有.jpg文件并查看每一帧的方法
2019/06/27 Python
Python函数的返回值、匿名函数lambda、filter函数、map函数、reduce函数用法实例分析
2019/12/26 Python
pytorch 自定义参数不更新方式
2020/01/06 Python
Python单链表原理与实现方法详解
2020/02/22 Python
美国NBA官方商店:NBA Store
2019/04/12 全球购物
ktv好的活动方案
2014/08/15 职场文书
小学生运动会报道稿
2014/09/12 职场文书
全国法制宣传日活动总结2014
2014/11/01 职场文书
银行招聘自荐信
2015/03/06 职场文书
监守自盗观后感
2015/06/10 职场文书
留学文书中的个人陈述,应该注意哪些问题?
2019/08/23 职场文书
Python深度学习之Pytorch初步使用
2021/05/20 Python
Spring Boot 排除某个类加载注入IOC的操作
2021/08/02 Java/Android
SQL Server中的逻辑函数介绍
2022/05/25 SQL Server