公司用的tp5.0,意外发现有现成的代码。
类名:think/App 文件名:/thinkphp/library/think/App.php 方法名:invokeClass
invokeClass这个方法根据构造参数是否为类处理,若为类则调用类的静态方法invoke或instance,获取类的实例。该方法可设置参数。
我第一次使用时报错,因为我设置的构造有两个参数,第一个设置类的类型,第二个没设置,传递参数的时候为第一个是实例,第二个是整数,返回处理过的参数为两个实例,正确的化应该是一个实例一个整数
就是因为第一个参数被当作类处理,没有使用传递的参数,而第二次设置值时使用第一个参数,用array_shift(传递的构造参数)获取和修改传递的构造参数,也就是传递的第二个参数一直没被使用。
一开始以为是源码的问题,所以另写一个类继承之后再改。改完调通,觉得自己多此一举。
既然一开始自己就想用设置好的实例作为参数,构造里不设置类的类型就好。再改代码,果然如此。
tp5.0代码如下
/**
* 调用反射执行类的实例化 支持依赖注入
* @access public
* @param string $class 类名
* @param array $vars 变量
* @return mixed
*/
public static function invokeClass($class, $vars = [])
{
$reflect = new \ReflectionClass($class);
$constructor = $reflect->getConstructor();
$args = $constructor ? self::bindParams($constructor, $vars) : [];
return $reflect->newInstanceArgs($args);
}
/**
* 绑定参数
* @access private
* @param \ReflectionMethod|\ReflectionFunction $reflect 反射类
* @param array $vars 变量
* @return array
*/
private static function bindParams($reflect, $vars = [])
{
// 自动获取请求变量
if (empty($vars)) {
$vars = Config::get('url_param_type') ?
Request::instance()->route() :
Request::instance()->param();
}
$args = [];
if ($reflect->getNumberOfParameters() > 0) {
// 判断数组类型 数字数组时按顺序绑定参数
reset($vars);
$type = key($vars) === 0 ? 1 : 0;
foreach ($reflect->getParameters() as $param) {
$args[] = self::getParamValue($param, $vars, $type);
}
}
return $args;
}
/**
* 获取参数值
* @access private
* @param \ReflectionParameter $param 参数
* @param array $vars 变量
* @param string $type 类别
* @return array
*/
private static function getParamValue($param, &$vars, $type)
{
$name = $param->getName();
$class = $param->getClass();
if ($class) {
$className = $class->getName();
$bind = Request::instance()->$name;
if ($bind instanceof $className) {
$result = $bind;
} else {
if (method_exists($className, 'invoke')) {
$method = new \ReflectionMethod($className, 'invoke');
if ($method->isPublic() && $method->isStatic()) {
return $className::invoke(Request::instance());
}
}
$result = method_exists($className, 'instance') ?
$className::instance() :
new $className;
}
} elseif (1 == $type && !empty($vars)) {
$result = array_shift($vars);
} elseif (0 == $type && isset($vars[$name])) {
$result = $vars[$name];
} elseif ($param->isDefaultValueAvailable()) {
$result = $param->getDefaultValue();
} else {
throw new \InvalidArgumentException('method param miss:' . $name);
}
return $result;
}
使用代码如下
//基础类
<?php
namespace app\index\server\finance\hireorder;
use app\index\model\enterprisemodel;
class Enterprise
{
private $fsinfo;
private $einfo;
public function __construct($fsinfo, $accountid)
{
$this->fsinfo = $fsinfo;
$this->setaccount($accountid);
}
private function setaccount($accountid)
{
var_dump($accountid);exit;
}
}
<?php
namespace app\index\server\finance;
use app\index\model\financesubjectmodel;
use think\App;
class Enterprise
{
private $allowmodelkey = ['hireorder'];
private $modelkey;
private $fsinfo;
public function __construct(financesubjectmodel $fsinfo)
{
$modelkey = $fsinfo['model_key'];
$this->modelkey = $modelkey;
$this->fsinfo = $fsinfo;
}
public function getclass($accountid)
{
$class = __CLASS__;
$class = explode('\\', $class);
$class[count($class) - 1] = $this->modelkey . "\\" . $class[count($class) - 1];
$classname = join('\\', $class);
$param = [
$this->fsinfo,
$accountid,
];
$obj = App::invokeClass($classname, $param);
return $obj;
}
}
<?php
namespace app\index\server;
use app\index\model\financesubjectmodel;
use app\index\server\finance\Enterprise;
use app\index\server\finance\Platform;
use app\index\server\finance\User;
class financesubjectserver
{
private $fsinfo;
private $accountid;
public function __construct($subjectkey, $accountid)
{
$m_fs = new financesubjectmodel();
$fsinfo = $m_fs->getInfo(['subject_use_key' => $subjectkey, 'status' => 1]);
$this->fsinfo = $fsinfo;
$this->accountid = $accountid;
}
public function getclass()
{
$fsinfo = $this->fsinfo;
$accountid = $this->accountid;
$s_obj = new Enterprise($fsinfo);
$s_obj = $s_obj->getclass($accountid);
return $s_obj;
}
}
//测试
use app\index\server\financesubjectserver;
class Test extends Controller
{
public function financeserver()
{
echo "<pre>";
$useobj = new financesubjectserver('enterprise_personal_tax', 12);
$useobj = $useobj->getclass();
}
}