【问题标题】:accessing private variable from member function in PHP从 PHP 中的成员函数访问私有变量
【发布时间】:2023-03-23 23:12:02
【问题描述】:

我从Exception派生了一个类,基本上是这样的:

class MyException extends Exception {

    private $_type;

    public function type() {
        return $this->_type; //line 74
    }

    public function __toString() {

        include "sometemplate.php";
        return "";

    }

}

然后,我像这样从MyException 导出:

class SpecialException extends MyException {

    private $_type = "superspecial";

}

如果我从一个函数中throw new SpecialException("bla"),捕获它,然后转到echo $e,那么__toString 函数应该加载一个模板,显示它,然后实际上不返回任何内容来回显。

这基本上就是模板文件中的内容

<div class="<?php echo $this->type(); ?>class">

    <p> <?php echo $this->message; ?> </p>

</div>

在我看来,这绝对应该有效。但是,当抛出异常并尝试显示它时,我收到以下错误:

致命错误:无法访问 C:\path\to\exceptions.php 中的私有属性 SpecialException::$_type 第 74

谁能解释我为什么在这里违反规则?我用这段代码做了一些非常机智的事情吗?有没有更惯用的方法来处理这种情况? $_type 变量的要点是(如图所示)我希望根据捕获的异常类型使用不同的 div 类。

【问题讨论】:

  • 正如我在那里写的:让 __toString() 返回一个空字符串是非常非常非常丑陋的。我真的看不到这些东西的任何用例。
  • 异常的__toString()空返回更值得怀疑。

标签: php oop exception


【解决方案1】:

使用 \Closure 有这种方法:

$reader = function ($object, $property) {
    $value = \Closure::bind(function () use ($property) {
         return $this->$property;
    }, $object, $object)->__invoke();

    return $value;
};

$myClass = new MyClass();
$property = $reader($myClass, 'yourProperty');
echo $property; // will display the value of property

【讨论】:

    【解决方案2】:

    无法在类之外访问 $this。 相反,需要调用类的一个实例。 然后,访问将返回消息的类中的函数。

    【讨论】:

    • 好吧,程序员会给出一个代码 sn-p 来清除问题。正确的? Here's 指导。谢谢。
    【解决方案3】:

    在这里查看我的答案: https://stackoverflow.com/a/40441769/1889685


    PHP 5.4 开始,您可以使用预定义的 Closure 类将类的方法/属性绑定到甚至可以访问私有成员的 delta 函数。

    The Closure class

    例如,我们有一个带有私有变量的类,我们想在该类之外访问它:

    class Foo {
        private $bar = "Foo::Bar";
    }
    

    PHP 5.4+

    $foo = new Foo;
    $getFooBarCallback = function() {
        return $this->bar;
    };
    
    $getFooBar = $getFooBarCallback->bindTo($foo, 'Foo');
    echo $getFooBar(); // Prints Foo::Bar
    

    从 PHP 7 开始,您可以使用新的 Closure::call 方法将对象的任何方法/属性绑定到回调函数,即使对于私有成员也是如此:

    PHP 7+

    $foo = new Foo;
    $getFooBar = function() {
        return $this->bar;
    };
    
    echo $getFooBar->call($foo); // Prints Foo::Bar
    

    【讨论】:

      【解决方案4】:

      只是一个如何访问私有财产的例子

      <?php
      class foo {
          private $bar = 'secret';
      }
      $obj = new foo;
      
      
      if (version_compare(PHP_VERSION, '5.3.0') >= 0)
      {
      
            $myClassReflection = new ReflectionClass(get_class($obj));
            $secret = $myClassReflection->getProperty('bar');
            $secret->setAccessible(true);
            echo $secret->getValue($obj);
      }
      else 
      {
          $propname="\0foo\0bar";
          $a = (array) $obj;
          echo $a[$propname];
      }
      

      【讨论】:

      • 我怎样才能做你在这里为二传手做的“其他”事情?
      【解决方案5】:

      在构建继承类时,您确实应该将 accessmodifier 更改为 protected

      不过还有一点;不要使用return "";,而是使用return;

      【讨论】:

      • 你的额外点会导致致命错误,我已经尝试过了 -- __toString() 必须返回一个字符串
      • 对不起!我查看了您的 __toString 函数.. 刚刚看到您返回“无”。你完全正确!
      • 让__toString()返回一个空字符串是非常非常非常难看的。我真的看不到这些东西的任何用例。但你是对的,__toString() 必须返回一个字符串。
      【解决方案6】:

      如果您查看visibility 文档,埋在评论中的是:

      //我们可以重新声明public和protected方法,但不能重新声明private

      你应该把它设为protected 去做你想做的事。

      顺便说一句,您似乎只是将其设置为类名 - 您可以使用 get_class()

      <div class="<?php echo get_class($this); ?>class">
      

      【讨论】:

      • 当然,但是如果我更改了(php)类名,我必须更改(css)类名,而且,如果我想在异常模板文件中使用更多信息,我可能会像添加“类型”属性一样添加它。
      【解决方案7】:

      您需要将访问权限设置为受保护。私有意味着它只能从它自己的类中访问,不能被继承。受保护的允许它被继承,但仍然不能从类外部直接访问。

      【讨论】:

        【解决方案8】:

        将变量命名为protected:

        * Public: anyone either inside the class or outside can access them
        * Private: only the specified class can access them. Even subclasses will be denied access.
        * Protected: only the specified class and subclasses can access them
        

        【讨论】:

        • 注意:在 PHP 中 protected 意味着你的父母也可以访问它们。
        • 好吧,我这样做了——但现在我不能使用$this-&gt;message——没有错误,它什么也不显示……为什么?
        • 没关系,我在父构造函数中设置了$message 而不是$this-&gt;message。此外,我意识到我没有提供有关如何设置消息的实际实现细节。我的坏
        猜你喜欢
        • 2021-02-04
        • 1970-01-01
        • 2010-09-30
        • 2019-07-12
        • 2015-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多