__get() 示例来自 Zandstra

发布于 2024-11-03 21:14:53 字数 883 浏览 0 评论 0原文

Matt Zandstra 在他的文章“PHP 对象模式与实践”中给出了以下示例来说明 __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() 来达到同样的目的吗?

询问的理由

如果我们要在对象中使用 name 和age 属性,那么 __get() 函数无论如何都不会被触发,因为尝试使用以下方法获取这些属性

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

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

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

Matt Zandstra gives the following example in his text "PHP Objects Patterns and Practice" to illustrate the __get() method:

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

In reality, we know we would never actually create such methods (getName and getAge) to return such static values, but instead - we would create name and age properties in the object and return those using the $this operator.

My question is whether this example actually shows utility. And if it does not, could somebody provide a better example of why one would use __get() for the same sort of purpose?

Justification for asking

If we were to use name and age properties in the object, then the __get() function would not be fired anyway, because attempting to get these properties with:

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

would cause either the name property to actually be returned if it were public, or cause a visibility error if it were private or protected. The __get() function would not be executed in either of these 'real' cases... am i missing something?

I'm fully aware that the above code works.
I am not convinced that it is a practical example.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

倾听心声的旋律 2024-11-10 21:14:53

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

使用魔术 __get 方法来调用方法是错误的,还有其他魔术方法专门用于这种用法:

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

__get()__set() 应用于读取和写入未声明的对象属性< /em>

You are absolutely right - I am impressed that you are quoting from a book, that example just plain sucks.

Using the magic __get method to call methods is just wrong, there are other magic methods just for that kind of usage:

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

__get() and __set() should be used to read and write non declared object properties.

夏了南城 2024-11-10 21:14:53

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

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

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

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

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

如何使用__get() 的两个示例是初始化实例化时可能不需要的属性(例如,通过数据库查询),从而减少开销。另一种可能是,如果您将属性存储在数组中,神奇的 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(),但原理是一样的。在这种情况下,这只是一个健全性检查。

The actual functionality of magical methods is totally up to the developer to handle in any way they see fit. The difference is in how they are invoked.

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

etc. So if you want to have __get() call a method internally, you can. How you want to handle it depends entirely on how you want to design your application.

About __get(), if you have a public member and try to call it with ->, the __get() will not fire. However, if you try to access a non-accessible member (either protected, private, or nonexistent) __get() will fire and you can handle it how you like.

It is my understanding that the main purpose of __get() at least according to php is to eliminate the need to write getters for every member. Compare with __set() for setters. I don't want to get into this here, but I think the use of getters/setters should raise some red flags about design. However, __get()'s intended purpose does not have to be adhered to except for the standards of those developing the application.

Two examples of how __get() might be used are to initialize a property that may not be needed upon instantiation (e.g. by a DB query) thus reducing overhead. Another may be if you have properties stored in an array, magical get may return the value mapped to the key of the requested property.

With the php magic functions, you can do some very cool things and you can write code that is more extensible by using these special invocations. Something I like to do:

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']();

Of course, this is using __call() rather than __get(), but the principle's the same. In this case it's just a sanity check.

思念绕指尖 2024-11-10 21:14:53

正如 php.net 所说

"__get()用于读取数据
来自无法访问的属性。”

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

,调用

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

即可 。但是,如果你调用 $a -> privateProperty ,你会得到一个错误,

$a -> getPrivateProperty() 

可以了

但是只要你定义了 __get() 就 。您调用 $a -> privateProperty,执行 __get() 并重定向到 $a -> getPrivateProperty()。你总会成功的获取值并仍然牢记安全性,因为您在 __get() 中检查属性 getter 是否存在,所以如果有人尝试访问不存在的属性,您可能会显示适当的错误或引发异常。属性,这将覆盖 php 的可见性错误。

As php.net states

"__get() is utilized for reading data
from inaccessible properties."

This means that __get() (if it's defined) is called whenever you try to access a property that does not exist or is private / protected. The above example shows a way for getting the values of those private properties by calling their accessors (getters) whenever someone tries to get the values.

For example, calling

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

would result in the same thing. However if you call $a -> privateProperty you would get an error, and

$a -> getPrivateProperty() 

would be OK.

But, if you defined __get() whenever you call $a -> privateProperty, __get() is executed and redirected to $a -> getPrivateProperty(). In this case you would always succeed in getting the value and still keeping security in mind. Even more, since you check for the existance of the property getter in __get() you could show an appropriate error or throw an exception if someone tries to access unexisting properties, which will override php's visibility errors.

擦肩而过的背影 2024-11-10 21:14:53
    <?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
    ?>
    <?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
    ?>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文