首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PHP7。反射不适用于旧版本php

PHP7。反射不适用于旧版本php
EN

Stack Overflow用户
提问于 2016-11-10 20:43:06
回答 1查看 596关注 0票数 0

我有一个php脚本,它是在php 5.6.19上编写的,在5.3版本上工作,并安装了一些插件。

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

通过使用Reflection::class创建一个新实例来通过引用来初始化带有参数的类的脚本的特殊性。在那里,警告,然后等待变量的参考,但价值收到。

类的构造函数方法的定义试图从以下位置创建实例:

代码语言:javascript
复制
public function __construct($user, IDatabase &$repository, $errors = null);

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

代码语言:javascript
复制
// 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);

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

代码语言:javascript
复制
$method = "show" . ucfirst($this->_page) . "Page";
$reflect->getMethod($method)->invoke($manager);

我没有看到任何文件的变化。有人有同样的问题吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-11-16 07:03:33

首先也是最重要的,为什么要通过引用传递对象呢?

对象具有逐个引用的语义,强制尝试通过引用传递对象自PHP 4以来就没有多大意义。

只要去掉& ..。

让我们忽略这一点,假装仍然有一个问题,这样你就可以试着去理解到底发生了什么。

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

代码语言:javascript
复制
mine(1 + 2);

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

代码语言:javascript
复制
mine(1);

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

代码语言:javascript
复制
mine($a);

我的参数有一个名称,您可以使用它来引用它的值。这是一个正常变量。

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

接下来,您需要理解为什么我们按引用传递:

代码语言:javascript
复制
function mine(int $thing) {
    $thing++;
}

$a = 1;

mine($a);

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

在这段代码中,$a通过值传递给mine(),因此mine()$thing所做的更改仅在mine的作用域中可见。$a在对mine()的调用返回后保持不变,因为$a$thing是不同的,它们是按值传递的,这意味着它的值被复制到调用堆栈上,以便调用mine()

代码语言:javascript
复制
function mine(int &$thing) {
    $thing++;
}

$a = 1;

mine($a);

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

在上面的代码中,$a是通过引用传递给mine()的,这意味着$a$thing不再是不同的。mine()$thing所做的更改现在在调用mine()返回后可见。

拼图中的最后一个部分是反射:

代码语言:javascript
复制
function mine(int &$thing) {
    $thing++;
}

$a = 1;

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

上述守则将提出:

代码语言:javascript
复制
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::newInstance)、按值接受它们的参数按值将它们传递给被调用的函数。

但是..。

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

代码语言:javascript
复制
class Foo {
    public function qux() {}
}

class Bar {}

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

$foo = new Foo;

mine($foo);

$foo->qux();

显然会产生:

代码语言:javascript
复制
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,应该避免。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40536651

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档