PHP-php 神秘问题

PHP-php 神秘问题

浮生未歇 发布于 2016-11-19 字数 866 浏览 1118 回复 6
<?php  
class Person
{
protected $_name = "phper";

protected $_age = 18;

public function getName()
{
$this = 123;
return $this->_name;
}

public function getAge()
{
return $this->_age;
}
}

$p = new Person();
$p->getName();
?>
代码会报错
改为
public function getName()
{
$a = "this";
$$a = 123;
echo $this;
return $this->_name;
}
可以顺利执行

如果改为
public function getName()
{
$a = "this";
$$a = 123;
$b = 123;
echo $this;
echo $b;
$this->getAge();
$b->getAge();
return $this->_name;
}
$this 和$b的值都是123,$this->getAge()可以顺利执行,$b->getAge()确报错,这是什么原因导致的?

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

夜无邪 2017-08-29 6 楼

我自己通过vld查看op的信息

$this->getAge()对应的为:

ZEND_INIT_METHOD_CALL RES[ IS_UNUSED ] OP1[ IS_UNUSED ] OP2[ IS_CONST (8142027) 'getAge' ]

$b->getAge()在对应的为:

ZEND_INIT_METHOD_CALL RES[ IS_UNUSED ] OP1[ IS_CV !0 ] OP2[ , IS_CONST (8142039) 'getAge' ]

虽然对应了同样的op code,但是由于操作数的不同(前者不使用OP1,后者使用OP1, 且OP1的值!0表示$b),同一个op code对应同一类handler,然后根据操作数的类型确定到此类handler中的某一个handler。

$this->getAge()对应的handler处理为:ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER

$b->getAge() 对应的handler处理为:ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER

调用getName的时候,getName()的作用域(scope)已经被设置成$name对象中,语法分析的时候对于getName中$this->getAge()这样的调用时只是在当前作用域(scope)中调用getAge()函数,不会理会$this的具体值,而在$b->getAge()这样的调用时,会关心$b所对应的值。

虐人心 2017-08-03 5 楼

我个人认为这样写很不规范,并不能体现开发者有多高明,尽量遵循标准话,常规话的编码方式来写PHP程序不更好么?像 $$ 这种 经常被用来 做面试题, 极端变态的一种做法,难道这样就能考察出PHP程序员高低来?

建议 不要这样使用,在这个地方深究没有很多实际意义吧

晚风撩人 2017-07-20 4 楼

这个问题很有趣。有点变魔术的感觉。楼上几位也不要抱怨楼主的用法不规范和没意义,就像魔术师从礼帽中扯出一只兔子一样,这本身不是件很好玩的事嘛。

我个人是这么理解的,在class中$this是一个虚拟变量,实际上它并不存在。而$a = "this";

$$a这个变量却是实体存在的,所以类中的$this与这个实体$$a没有发生数据冲突。

第一个报错是因为此时的$this是虚拟变量,因此不能直接赋值。

第二个echo $this;此时$this通过旁门左道的办法,已经变成一个实体变量了。系统优先匹配实体变量,若无实体变量,则再匹配成class内适用的虚拟变量。

而return $this->_name;这个被系统识别成虚拟变量,而且是绝对优先级,不容许任何实体变量挑战。

下面这个例子就是很好的说明:

class a
{
public $c;
function __construct()
{
$this -> c = '5555..';
$b = 'this';
$$b = new aa();
var_dump($this -> cc);
var_dump($this);
var_dump($$b -> cc);
}
}

class aa
{
public $cc;
function __construct()
{
$this -> cc = '123';
}
}

$a = new a();

第三个就很好解释了,跟上面代码同理,$this->getAge()中虚拟变量获得了绝对的优先级。

浮生未歇 2017-05-17 3 楼

代码写得有问题,PHP是解释执行的代码,默认变量不会自动初始化,在界面解析器中$p = new Person(); 中的$this在这时候已经确定了,不能被再次修改,所以 $this = 123;这句肯定出错,其他两个出错的原因类似。

晚风撩人 2017-03-04 2 楼

$this = 123 就算赋值成功了也是$this 的一个对象。只是变量名变了吧。
而$b = 123 只是一个普通的变量,能调用方法吗?
对象和变量的概念没有搞清楚吧。

灵芸 2016-12-02 1 楼

……为什么这样做呢?对$this赋值是不合规则的,也没有深入研究的意义,即便你能够通过反射去修改$this的值,那也只能说是PHP不完善导致的