代码之家  ›  专栏  ›  技术社区  ›  user6818018

使用构造访问面向对象php中的公共对象

  •  0
  • user6818018  · 技术社区  · 8 年前

    更新时间:

    我想了解一些关于面向对象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\u key。

    我不明白为什么。变量应该是全局的(在本例中是数组),加上我使用的是\uu构造,所以我应该在代码中的任何地方都可以访问该函数。

    更新:$clean\u key返回null和$this->clean\u key返回如下数组:

    array(0) {
    }
    
    2 回复  |  直到 8 年前
        1
  •  0
  •   ArtisticPhoenix    8 年前

    我发现这有几个问题

    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\u密钥 你必须使用 $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通话时,它会提前绑定并且上课 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 东西更有意义。

    • public=可在课堂外和扩展课堂的所有儿童中访问
    • protected=仅在类和扩展类的任何子级内可访问
    • private=只能在类中访问
        2
  •  0
  •   MonkeyZeus    8 年前

    没有理由 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!"
    }
    
    推荐文章