PHP-php 神秘问题
<?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()确报错,这是什么原因导致的?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(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所对应的值。
我个人认为这样写很不规范,并不能体现开发者有多高明,尽量遵循标准话,常规话的编码方式来写PHP程序不更好么?像 $$ 这种 经常被用来 做面试题, 极端变态的一种做法,难道这样就能考察出PHP程序员高低来?
建议 不要这样使用,在这个地方深究没有很多实际意义吧
这个问题很有趣。有点变魔术的感觉。楼上几位也不要抱怨楼主的用法不规范和没意义,就像魔术师从礼帽中扯出一只兔子一样,这本身不是件很好玩的事嘛。
我个人是这么理解的,在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()中虚拟变量获得了绝对的优先级。
代码写得有问题,PHP是解释执行的代码,默认变量不会自动初始化,在界面解析器中$p = new Person(); 中的$this在这时候已经确定了,不能被再次修改,所以 $this = 123;这句肯定出错,其他两个出错的原因类似。
$this = 123 就算赋值成功了也是$this 的一个对象。只是变量名变了吧。
而$b = 123 只是一个普通的变量,能调用方法吗?
对象和变量的概念没有搞清楚吧。
……为什么这样做呢?对$this赋值是不合规则的,也没有深入研究的意义,即便你能够通过反射去修改$this的值,那也只能说是PHP不完善导致的