3

Matt Zandstra 在他的文章“PHP Objects Patterns and Practice”中给出了以下示例来说明 __get() 方法:

class Person {
    function __get( $property ) {
        $method = "get{$property}";
        if ( method_exists( $this, $method ) ) {
            return $this->$method();
        }
    }
    function getName() {
        return "Bob";
    }
    function getAge() {
        return 44;
    }
}

实际上,我们知道我们永远不会真正创建此类方法(getName 和 getAge)来返回此类静态值,而是 - 我们将在对象中创建名称和年龄属性并使用 $this 运算符返回这些属性。

我的问题是这个例子是否真的显示了实用性。如果没有,有人可以提供一个更好的例子来说明为什么人们会出于同样的目的使用 __get() 吗?

询问的理由

如果我们要在对象中使用姓名和年龄属性,那么无论如何都不会触发 __get() 函数,因为试图通过以下方式获取这些属性:

$person = new Person();
$name = $person->name;

如果 name 属性是公共的,则会导致实际返回,或者如果它是私有的或受保护的,则会导致可见性错误。__get() 函数在这两种“真实”情况下都不会执行……我错过了什么吗?

我完全知道上面的代码有效。我不相信这是一个实际的例子。

4

4 回答 4

1

你是绝对正确的——你引用一本书给我留下了深刻的印象,那个例子简直糟透了。

使用魔术__get方法调用方法是错误的,还有其他魔术方法只是为了这种用法:

  • __call()
  • __callStatic()
  • __invoke()

__get()并且__set()应该用于读取和写入未声明的对象属性

于 2011-04-27T23:07:35.703 回答
0

正如 php.net 所说

“__get() 用于从不可访问的属性中读取数据。”

这意味着__get()每当您尝试访问不存在或私有/受保护的属性时都会调用(如果已定义)。上面的示例显示了一种通过在有人尝试获取值时调用它们的访问器(getter)来获取这些私有属性值的方法。

例如,调用

echo $a -> publicPropery or echo $a -> getPublicProperty()

会导致同样的事情。但是,如果你调用 $a -> privateProperty 你会得到一个错误,并且

$a -> getPrivateProperty() 

会好的。

但是,如果您__get()在调用时定义了$a -> privateProperty__get()则执行并重定向到$a -> getPrivateProperty(). 在这种情况下,您将始终成功获得价值并仍然牢记安全性。更重要的是,由于您检查了属性 getter 的存在,__get()如果有人试图访问不存在的属性,您可能会显示适当的错误或抛出异常,这将覆盖 php 的可见性错误。

于 2011-04-27T23:18:57.487 回答
0

神奇方法的实际功能完全取决于开发人员以他们认为合适的任何方式处理。不同之处在于它们的调用方式。

$obj->property; // invokes __get(), if defined
$obj->method(); // invokes __call(), if defined
$obj(); // invokes __invoke() if defined (php 5.3+)

等等。所以如果你想在__get()内部调用一个方法,你可以。你想如何处理它完全取决于你想如何设计你的应用程序。

关于__get(),如果您有一个公共成员并尝试使用 调用它->__get()则不会触发。但是,如果您尝试访问不可访问的成员(受保护的、私有的或不存在的)__get()将会触发,您可以按照自己的喜好进行处理。

据我了解,__get()至少根据 php 的主要目的是消除为每个成员编写 getter 的需要。与__set()二传手进行比较。我不想在这里讨论这个问题,但我认为使用 getter/setter 应该会引发一些关于设计的危险信号。但是,__get()除了开发应用程序的标准外,不必遵守 的预期目的。

如何使用的两个示例__get()是初始化在实例化时可能不需要的属性(例如,通过 DB 查询),从而减少开销。另一个可能是如果您将属性存储在数组中,神奇的 get 可能会返回映射到所请求属性的键的值。

使用 php 魔术函数,您可以做一些非常酷的事情,并且可以通过使用这些特殊调用编写更具扩展性的代码。我喜欢做的事情:

class application {
   public function __call($_, $_) {
      throw new Exception("PUT and DELETE not supported");
   }
   public function POST() {
      //update data
      header("Location: $_SERVER[PHP_SELF]", true, 303);
   }
   public function GET() {
      //display data
   }
   public static function inst() {
      return new self;
   }
}

application::inst()->$_SERVER['REQUEST_METHOD']();

当然,这是使用__call()而不是__get(),但原理是一样的。在这种情况下,它只是一个健全性检查。

于 2011-04-27T23:28:09.850 回答
0
    <?php
        class data {
            public $name="Ankur DalsaniYa"; \\ I wont to change name

            public function __get($var) {
                print "Attempted to retrieve '<b>$var</b>' and failed...\n";
                //$var is print the Unknown and Not Define but call variable print  
            }
        }

        $data = new data;
        echo "<br> Not Define Variable Call : ";
        print $data->title; // Not Defined variable Call then call __get function
        echo "<br><br> Define Variable Call : ";
        print $data->name;  // Define variable Call then Not call __get function
    ?>
于 2015-07-14T17:46:43.767 回答