PHP7。反思并不适用于旧版本的php

时间:2016-11-10 20:43:06

标签: reflection php-7

我有一个php脚本,写在php 5.6.19上,适用于5.3版本,有一些已安装的插件。

我决定尝试在php7上执行它。

通过使用Reflection::class创建新实例,我通过引用初始化类的脚本的特殊性。然后有警告然后通过引用等待变量,但收到了价值。

班级定义'构造函数方法尝试从:

创建实例
public function __construct($user, IDatabase &$repository, $errors = null);

使用此构造函数的代码示例:

// define manager type to create (all managers has the same constructor)
$manager = $managersNamespace . ucfirst($this->_manager) . "Manager";
// trying to create the manager
// !!!And here a Warning occurs
$reflect = new \ReflectionClass($manager);
$manager = $reflect->newInstance($user, $database, $errors);

在这些之后我调用了一个我需要的方法,这里的致命错误就停止了脚本:

$method = "show" . ucfirst($this->_page) . "Page";
$reflect->getMethod($method)->invoke($manager);

我没有看到文档中的任何更改。有人有同样的问题吗?

1 个答案:

答案 0 :(得分:6)

首先,为什么要通过引用传递对象!?

对象具有传递引用语义,因为 PHP 4 ,强制尝试通过引用传递对象没有多大意义。

只需删除& ...

即可

让我们忽略它,并假装仍然存在问题,以便您可以尝试了解发生了什么。

要解决问题,首先需要了解变量和表达式之间的区别:

mine(1 + 2);

我的论点没有名称,它由引擎中的临时变量表​​示:它是一个表达式。

mine(1);

我的参数没有名称,它不是表达式,而是一个文字常量,由引擎中的编译器变量表示。它类似于临时变量,一种常量表达式。

mine($a);

我的论点有一个名字,你可以用来引用它的价值。这是一个正常变量。

只能通过引用传递变量,因为你不能引用表达式或文字常量

接下来,您需要了解我们传递参考的原因:

function mine(int $thing) {
    $thing++;
}

$a = 1;

mine($a);

var_dump($a); // int(1)

在此代码中,$a按值传递给mine(),以便mine()$thing所做的更改仅在{{1}的范围内可见}}。调用mine后,$a保持不变,因为mine()$a是不同的,已按值传递,这意味着它的值已被复制调用$thing

的调用堆栈
mine()

在上面的代码中,function mine(int &$thing) { $thing++; } $a = 1; mine($a); var_dump($a); // int(2) 通过引用传递给$a,这意味着mine()$a不再是不同的。调用$thing后,mine()$thing的更改现已显示。

拼图中的最后一块是反思:

mine()

上面的代码会提出:

function mine(int &$thing) {
    $thing++;
}

$a = 1;

$reflector = new ReflectionFunction("mine");
$reflector->invoke($a);

这是因为Warning: Parameter 1 to mine() expected to be a reference, value given in /usr/src/php-src/refs.php on line 9 和类似的反射函数(ReflectionFunction::invokeaccept their parameters by valuepass them onto the invoked function by value

但是......

传递引用语义与传递引用之间仍存在差异,这是一个危险的:

ReflectionClass::newInstance

显然会产生:

class Foo {
    public function qux() {}
}

class Bar {}

function mine(Foo &$foo) {
  $foo = new Bar();        
}

$foo = new Foo;

mine($foo);

$foo->qux();

PHP Fatal error: Uncaught Error: Call to undefined method Bar::qux() in /usr/src/php-src/refs.php:16 Stack trace: #0 {main} thrown in /usr/src/php-src/refs.php on line 16 的声明说明了它的参数的类型安全性。只有在进入函数时才能保证类型安全,函数体可以自由地破坏类型安全性,但是当依赖引擎传递对象的引用语义时,它通常不会影响调用者。

这是一种非常可怕的API,应该避免使用。