2016-11-10 70 views
0

我有一个PHP脚本,这是写在PHP 5.6.19,工程5.3版本,与一些安装插件。PHP7。反射不适用于旧版本php

我决定尝试在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); 

我没有看到一个ny文件更改。任何人都有同样的问题?

+2

您收到了什么错误? – bishop

+0

而不是一个coupla断开连接的代码片段,你能给我们一个SSCCE来证明确切的问题,只有问题,所以我们可以运行它比较? –

+0

我试着猜测这个SSCCE可能是什么 - http://sandbox.onlinephpfunctions.com/code/9a32f440e3939f845a9b1c26bc2f06408abbf5cd - 它在5.6和7.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的更改仅在mine的范围内可见。由于$a$thing是不同的,已经传值了,这意味着它的值被复制到调用栈的调用中,因此$a在对mine()返回的调用之后没有变化。

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

$a = 1; 

mine($a); 

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

在上面的代码,$a通过引用传递到mine(),这意味着$a$thing不再明显。在致电mine()返回后,现在可以看到mine()$thing的更改。

在拼图最后一块是反射:

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::invoke和类似反射功能(ReflectionClass::newInstanceaccept their parameters by valuepass them onto the invoked function by value

但是...

还有通通过引用语义之间的差异,并通过引用传递,一个危险的:

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 

mine()的声明告诉我们它的参数的类型安全的谎言。类型安全只有在进入函数时才能得到保证,函数体可以自由地破坏类型安全,但是当依赖引擎通过引用语义传递对象时,它通常不会影响调用者。

这是一个非常可怕的API,应该避免。

+0

谢谢。你是对的 –