说明
在研究过程中,我在下面创建了这个小代码片段,以便更好地了解php。我现在提出这个问题的原因是为了接触到更有经验的开发人员,以免过多地阻塞系统,也不会让它走得更远
下面是一个关于如何访问类作用域之外的私有或受保护变量的代码示例。
代码示例
此代码示例将$TestVar
设置为对test
类内部的私有变量test::A
的引用。
<?php
class Test {
private $A = 123;
public function changeA ($Var){
$this->A = $Var;
}
public function createReference(){
return([&$this->A]);
}
}
$TestClass = new Test();
$TestVar = &$TestClass->createReference()[0];
通过使用Test::changeA()
或改变$TestVar
,可以改变test::A
的内容。
//Test Current Value
var_dump($TestVar);
//Change test::A the intended way
$TestClass->changeA(321);
var_dump($TestVar);
//Change it by reference
$TestVar = 777;
var_dump($TestVar);
var_dump($TestClass);
预期输出:
int 123
int 321
int 777
object(Test)[1]
private 'A' => int 777
结果
我认为这是一个错误的原因,手册在描述和示例中都有说明:
声明受保护的成员只能在类本身内以及通过继承类和父类进行访问。
声明为私有的成员只能由定义该成员的类访问。
这是不可能或不打算的。
这是一个错误,一个错误的文档,还是仅仅是一个必须面对的错误。
这种行为完全正常。事实上,如果你的属性是对象(总是通过引用传递(,你甚至不需要显式地创建引用:
class Foo
{
private Datetime $when;
public function __construct()
{
$this->when = new DateTime('1950-12-31');
}
public function getWhen(): DateTime
{
return $this->when;
}
}
$f = new Foo();
$w = $f->getWhen();
$w->modify('+50 years');
var_dump($w, $f);
object(DateTime)#2 (3) {
["date"]=>
string(26) "2000-12-31 00:00:00.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(13) "Europe/Madrid"
}
object(Foo)#1 (1) {
["when":"Foo":private]=>
object(DateTime)#2 (3) {
["date"]=>
string(26) "2000-12-31 00:00:00.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(13) "Europe/Madrid"
}
}
这与你引用的文件并不矛盾。属性本身无法访问:
$f->when;
// PHP Fatal error: Uncaught Error: Cannot access private property Foo::$when
引用是另一种语言功能。也许用另一个例子更容易理解:
function a(){
$local_variable = 1;
b($local_variable);
echo "b modified a's local variable: $local_variablen";
}
function b(&$number)
{
echo "b can read a's local variable: $numbern";
$number++;
}
a();
b can read a's local variable: 1
b modified a's local variable: 2