2016-11-10 66 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

謝謝。你是對的 –

相關問題