更新:
我正在尝试理解面向对象的PHP。
假设我在我的代码的最顶部用其他数组和函数(修饰符)定义我的变量:
class Shipments {
public $clean_key = [];
}
我正试图以这种方式在我的公共数组中推送一个数组:
class Shipments {
public function __construct($settings = array())
{
$use_access_key = $this->access_key();
$this->ee = ee();
$this->settings = $settings;
$sql = ee()->db->select('*')->from('exp_extensions')->where('class', __CLASS__)->get();
foreach ($sql->result() as $row) {
array_push($this->clean_key, unserialize($row->settings));
}
}
然后我用这种方式在另一个函数中调用它:
public function access_key()
{
echo "<pre>";
var_dump($this->clean_key);
die();
if (isset($clean_key['mode']) && $clean_key['mode'] == "0") {
if (isset($clean_key['access_key_test'])) {
$this->access_key = array($clean_key['access_key_test']);
}
} elseif (isset($clean_key['mode']) && $clean_key['mode'] == "1") {
if (isset($clean_key['access_key_production'])) {
$this->access_key = array($clean_key['access_key_production']);
}
}
我的数组看起来像这样:
array(2) {
[0]=>
array(27) {
["access_key_test"]=>
string(22) "blabla11"
["access_key_production"]=>
string(0) ""
["mode"]=>
string(1) "0"
["ExpeditedParcel"]=>
string(1) "1"
["ExpeditedParceldrop"]=>
}
如果我在我的代码之后立即转储我的数组,我就会得到我正在寻找的东西。问题是,如果我出于某种原因尝试从任何其他实例访问该数组,我无法访问我的公共数组,例如:
public function access_key()
{
var_dump($this->clean_key);
die();
}
它返回一个未定义的变量:clean_key。
我不明白为什么。变量应该是全局的(在这种情况下是数组)加上我使用__construct所以我应该可以在我的代码中到处访问函数。
更新:$ clean_key返回null,$ this-&gt; clean_key返回类似的arry:
array(0) {
}
答案 0 :(得分:1)
我看到了这个
的几个问题public function access_key()
{
if (isset($clean_key['mode']) && $clean_key['mode'] == "0") {
if (isset($clean_key['access_key_test'])) {
$this->access_key = array($clean_key['access_key_test']);
}
} elseif (isset($clean_key['mode']) && $clean_key['mode'] == "1") {
if (isset($clean_key['access_key_production'])) {
$this->access_key = array($clean_key['access_key_production']);
}
}
}
$clean_key
是一个局部变量,其范围仅存在于方法中,以访问您必须使用的$clean_key
属性$this->clean_key
$this->access_key
未被提及作为属性,但它被列为一种方法,您无法将方法设置为相等。您可以拥有与方法同名的属性,但在我的意见中这是一个不好的做法,因为它可能会导致混淆。我不知道这些是否只是问题中的拼写错误,但我不得不提及它们。
就此而言
问题是,如果我尝试从任何其他实例访问该数组
这是预期的行为,因为(非静态)属性的范围仅存在于您创建的类的实例中。
您可以将此属性设置为静态,并且可以从同一个请求(PHP实例)中的任何实例访问它。但是,当您必须动态设置静态通常不是最好的方法时,因为您必须确保在使用它之前设置它,并且它可能被另一个实例更改并在当前实例中产生意外结果。
class Shipments {
public static $clean_key = [];
}
要在类的另一个方法中访问它,你必须使用self::$clean_key
或static::$clean_key
,通常self会正常工作,除非你创建这个类固有的子类,然后你可能会需要late static binding又名static
。
这是一个快速示例,显示两者之间的区别:
class p{
public function test(){
return "test";
}
public function foo(){
echo "Self: ".self::test() . PHP_EOL;
echo "Static: ".static::test() . PHP_EOL;
}
}
class c extends p{
public function test(){
return "new";
}
}
$C = new c();
$C->foo();
输出
Self: test
Static: new
在线测试
http://sandbox.onlinephpfunctions.com/code/268e95a28663f4e8d6172cb513a8b3cf1ad5d929
正如您所看到的那样,在使用self进行调用时,self
一次static
调用同一方法,它只提前绑定,仅限p
类了解它自己的方法。当它迟到时,它知道类c
及其方法。 c
类扩展了p
类,并替换了对输出有影响的方法之一。因此,如果没有使用后期静态绑定的调用,我们可能会从父类中获得意外结果,因为人们会期望该方法被子类覆盖。这就是为什么我说它在扩展课程时主要有影响。
希望有所帮助,因为它可能是一个非常令人困惑的概念。
关于公共财产的说明(免责声明,这是我的意见)
我避免使用类的公共属性,因为它不是S.O.L.I.D。基本上可能发生的事情是你可以更改属性的名称或删除它等等。现在因为它可以在外部访问,你必须搜索所有代码来重构这个变化。访问类外的方法更清晰,因为它们的内部实现对外部代码不重要(也不应该)。您可以重构一个方法的内容,只要参数和返回值不会改变太多,您就不必触及类外的任何其他代码。
所以不要做这样的事情:
class foo{
public $bar;
}
$foo = new foo();
echo $foo->bar;
我更喜欢这样做:
class foo{
protected $bar;
}
$foo = new foo();
echo $foo->getBar();
请参阅因为课程内部我们可以重新定义getBar
我们想要的所有内容,但如果我们对$foo->bar
进行任何更改,则会中断。
现在在某些情况下,这是非常好的,例如一个充当数据存储等的类。它只是需要注意的东西,而且它通常是气馁的。它还有助于public, protected, private
的内容更有意义。
答案 1 :(得分:0)
access_key()
方法没有理由告诉您clean_key
变量未定义。见下文:
<?php
class a{
public $clean_key = [];
public function __construct($settings)
{
echo "before push:<br>\r\n";
var_dump($this->clean_key);
array_push($this->clean_key, $settings);
echo "after push:<br>\r\n";
var_dump($this->clean_key);
}
public function access_key()
{
echo "access_key() method:\r\n";
var_dump($this->clean_key);
}
}
$a = new a('hey!');
$a->access_key();
产生
before push:<br>
array(0) {
}
after push:<br>
array(1) {
[0]=>
string(4) "hey!"
}
access_key() method:
array(1) {
[0]=>
string(4) "hey!"
}