简体   繁体   English

如何在PHP中的Overloading(使用__get()魔术方法或其他方法)类之外访问现有的私有属性?

[英]How can I access an existing private property out of the class in Overloading(using __get() magic method or some other way) in PHP?

Consider below working code : 考虑以下工作代码:

<?php
  class PropertyTest {
    /**  Location for overloaded data.  */
    private $data = array();

    /**  Overloading not used on declared properties.  */
    public $declared = 1;

    /**  Overloading only used on this when accessed outside the class.  */
    private $hidden = 2;

    public function __set($name, $value) {
      echo "Setting '$name' to '$value'\n";
      $this->data[$name] = $value;
    }

    public function __get($name) {
      echo "Getting '$name'\n";
      if (array_key_exists($name, $this->data)) {
        return $this->data[$name];
      }

      $trace = debug_backtrace();
      var_dump($trace); die;
      trigger_error(
        'Undefined property via __get(): ' . $name .
        ' in ' . $trace[0]['file'] .
        ' on line ' . $trace[0]['line'],
        E_USER_NOTICE);
        return null;
    }

    /**  As of PHP 5.1.0  */
    public function __isset($name) {
      echo "Is '$name' set?\n";
      return isset($this->data[$name]);
    }

    /**  As of PHP 5.1.0  */
    public function __unset($name) {
      echo "Unsetting '$name'\n";
      unset($this->data[$name]);
    }

    /**  Not a magic method, just here for example.  */
    public function getHidden() {
      return $this->hidden;
    }
  }


  echo "<pre>\n";

  $obj = new PropertyTest;

  $obj->a = 1;
  echo $obj->a . "\n\n";

  var_dump(isset($obj->a));
  unset($obj->a);
  var_dump(isset($obj->a));
  echo "\n";

  echo $obj->declared . "\n\n";

  echo "Let's experiment with the private property named 'hidden':\n";
  echo "Privates are visible inside the class, so __get() not used...\n";
  echo $obj->getHidden() . "\n";
  echo "Privates not visible outside of class, so __get() is used...\n";
  echo $obj->hidden . "\n";
?>

Output : 输出:

Setting 'a' to '1'
Getting 'a'
1

Is 'a' set?
bool(true)
Unsetting 'a'
Is 'a' set?
bool(false)

1

Let's experiment with the private property named 'hidden':
Privates are visible inside the class, so __get() not used...
2
Privates not visible outside of class, so __get() is used...
Getting 'hidden'


Notice:  Undefined property via __get(): hidden in <file> on line 70 in <file> on line 29 

I understood everything in the code. 我了解代码中的所有内容。 I only have a concern in accessing the private property $hidden outside the class using magic method __get()(or some other way but in overloading). 我只关心使用魔术方法__get()(或其他方法,但有重载)访问类外部的私有属性$hidden I mean by usage of Overloading only. 我的意思是仅使用重载

But currently I'm not able to achieve that. 但目前我无法实现这一目标。 Getting User Notice for the same. 获取用户通知同样。

I don't understand your problem 我不明白你的问题

 <?php
    class TestClass{

        private $private = 'true';

        public function __get($key){
            if( isset($this->{$key}) ){
                return $this->{$key};
            }
            throw new Exception('Undefined object property '.__CLASS__.'::'.$key);
        }
    }

echo (new TestClass())->private;

Outputs 输出

true

See for yourself here 在这里自己看看

There is no reason you can't do that from the class where $private is defined in. That said it's probably a poor design choice. 没有理由在定义$private的类中不能这样做。那可能是一个糟糕的设计选择。

Now if you are trying to do this ( Access private parent property from a child ) 现在,如果您尝试执行此操作(从孩子访问私有父属性)

<?php
    class TestClass{
        private $private = 'true';
    }

    class ChildClass extends TestClass{            
        public function __get($key){
            if( isset($this->{$key}) ){
                return $this->{$key};
            }
            throw new Exception('Undefined object property '.__CLASS__.'::'.$key);
        }
    }

echo (new ChildClass())->private;

Outputs ( our exception ) 输出(我们的例外)

<b>Fatal error</b>:  Uncaught Exception: Undefined object property ChildClass::private in

See it here 在这里看到

Indeed, and if you want to get real Crazy you can do this: 确实,如果您想变得真正的疯狂 ,可以这样做:

<?php
    class TestClass{
        private $private = 'true'; //not visible to child

         //called -via- child class
        public function parentEcho(){
            echo "\nParent: {$this->private}\n";
            return $this; //return this for chaining
        }
    }

    class ChildClass extends TestClass{
        private $private = 'false'; //this is not parent::$private

        public function childEcho(){
            echo "\nChild: {$this->private}\n";
            return $this;
        }
    }

(new ChildClass())->childEcho()->parentEcho();

Outputs 输出

Child: false

Parent: true

Check this out here 在这里查看

This illustrates the scope of a private property Is only within this class. 这说明了private属性的范围仅在this之内。 Even children know nothing about it. 甚至孩子对此一无所知。 However with a method in parent that accesses is directly ( not overwritten in child ) it can still be reached by inheritance. 但是,使用父级中直接访问的方法(不会在子级中覆盖),继承仍然可以访问它。 Because, the child inherits the method and the method is defined within the class ( parent ) which can access it. 因为,子级继承了该方法,并且该方法是在可以访问它的类(父级)中定义的。

But if you truly want your mind blown (Reflection) : 但是,如果您确实希望自己的想法被打击(反思)

<?php
    class TestClass{
        private $private = 'true';

        public function parentEcho(){
            echo "\nParent: {$this->private}\n";
            return $this;
        }
    }

$Obj = new TestClass();

$Obj->parentEcho();

echo "\n";

$ReflectionObj = new ReflectionObject($Obj);

$ReflectionProperty = $ReflectionObj->getProperty('private');
$ReflectionProperty->setAccessible(true);

echo $ReflectionProperty->getValue($Obj)."\n";

$ReflectionProperty->setValue($Obj, 'false' );

echo $ReflectionProperty->getValue($Obj)."\n";

$Obj->parentEcho();

Outputs 输出

Parent: true

true
false

Parent: false

You can see this darling here 你可以在这里看到这个宝贝

Reflection allows you to inspect the definition of other Objects, methods, function etc... (introspection) from outside of them. 反射使您可以从外部检查其他对象,方法,函数等的定义(自省)。 I am not to sure with recent versions of PHP, but in the past their was a significant performance hit when using reflection (it wasn't like seconds, more like 10s of milliseconds ). 我不确定最新版本的PHP,但是在过去,使用反射时它们对性能产生了重大影响(这不像秒,更像是10毫秒)。 However, there are some really neat things you can do with it. 但是,您可以使用它进行一些真正整洁的操作。

http://php.net/manual/en/intro.reflection.php http://php.net/manual/en/intro.reflection.php

That all said, you can access it with a simple get method, and semantically that is probably the best way. 综上所述,您可以使用简单的get方法访问它,从语义上来说,这可能是最好的方法。

public method getProperty() {
    return $this->property;
}
public method setProperty($property) {
    return $this->property = $property;
}

A few things I feel I must mention 我觉得我必须提到的几件事

  • I rarely, rarely, rarely ever use private properties. 我很少,很少,很少使用private财产。 The problem with private properties is if you decide to extend the class, later, you'll wind up changing most of them over to protected anyway. 私有属性的问题是,如果您决定扩展该类,则以后,您最终会将它们中的大多数更改为protected的。 private - visible only within the scope of this class. 私有 -仅在this的范围内可见。

  • I use protected Something like 99% of the time. 我有99%的时间使用protected的内容。 It just works. 它只是工作。 protected - visible only within the scope of this class's descendants. 保护 -仅在此类后代的范围内可见。

  • I refuse to use public properties as it's a poor design, IMO, that leads to a lot of woes when it comes time to maintain your code. 我拒绝使用public属性,因为它是一个糟糕的设计,IMO,在维护代码时会带来很多麻烦。 Classes should be Black Boxes , which means the internal workings of them should not be exposed to the rest of your code. 类应该是Black Boxes ,这意味着它们的内部工作不应暴露于代码的其余部分。 The problem with exposing all the workings of you class is you could rename a property without thinking and break some piece of code somewhere. 公开类的所有工作的问题是,您可以重命名属性而无需考虑并在某些地方破坏一些代码。 At least with public methods you can rename the properties, re-work the method and nothing outside the class should be affected (as long as the method name, inputs, and outputs don't change) public - visible within the scope of the caller (and class's descendants) 至少在公开方法,你可以重命名的属性,重新工作类之外的方法并没有什么应该受到影响(只要方法名,输入和输出不会改变) 公共 -可见呼叫者的范围之内(以及班级的后代)

Cheers, and happy coding. 欢呼,编码愉快。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在C#中获取和设置(私有)属性,而不使用getter setter魔术方法重载 - Get and set (private) property in PHP as in C# without using getter setter magic method overloading __get 魔术方法 - 如何抛出和捕获属性重载的错误? - __get magic method - how to throw and catch error for property overloading? 为什么我可以在父PHP类中访问私有财产? - Why I can access private property in parent php class? 在PHP中“重载”一个私有方法 - “Overloading” a private method in PHP 如何以适当的方式扩展某些php类,以便从子类访问其他子类的所有公共方法? - How can extend in proper way some php classes for have access from child class to all public methods from other child class? 如何使用 STATIC 方法从 PHP 中的不同 class 访问 class 属性? - How do i access class property using STATIC method from a different class in PHP? PHP类的私有属性和方法 - PHP class private property and method 如何通过静态方法访问属性? - How can I access a property out of the static method? PHP:如何通过反射或其他方式从子 class 获取父抽象 class 私有属性 - PHP: How to get parent abstract class private property from child class with reflections or with another way PHP:我可以在方法重载(__get)中获得数组功能吗? - PHP: Can I get array functionality in method overloading (__get)?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM