最佳实践:PHP 魔术方法__set和__get

2022-08-30 07:05:23

可能的重复:
魔术方法在PHP中是最佳实践吗?

这些都是简单的示例,但假设您的类中的属性比两个属性多。

什么是最佳实践?

a) 使用__get和__set

class MyClass {
    private $firstField;
    private $secondField;

    public function __get($property) {
            if (property_exists($this, $property)) {
                return $this->$property;
            }
    }

    public function __set($property, $value) {
        if (property_exists($this, $property)) {
            $this->$property = $value;
        }
    }
}

$myClass = new MyClass();

$myClass->firstField = "This is a foo line";
$myClass->secondField = "This is a bar line";

echo $myClass->firstField;
echo $myClass->secondField;

/* Output:
    This is a foo line
    This is a bar line
 */

b) 使用传统的二传手和收盘机

class MyClass {

    private $firstField;
    private $secondField;

    public function getFirstField() {
        return $this->firstField;
    }

    public function setFirstField($firstField) {
        $this->firstField = $firstField;
    }

    public function getSecondField() {
        return $this->secondField;
    }

    public function setSecondField($secondField) {
        $this->secondField = $secondField;
    }

}

$myClass = new MyClass();

$myClass->setFirstField("This is a foo line");
$myClass->setSecondField("This is a bar line");

echo $myClass->getFirstField();
echo $myClass->getSecondField();

/* Output:
    This is a foo line
    This is a bar line
 */

本文内容: http://blog.webspecies.co.uk/2011-05-23/the-new-era-of-php-frameworks.html

作者声称使用魔术方法不是一个好主意:

首先,当时使用PHP的魔术功能(__get,__call等)非常流行。从第一眼看它们没有错,但它们实际上真的很危险。它们使API不清楚,自动完成是不可能的,最重要的是它们很慢。他们的用例是破解PHP来做它不想做的事情。它奏效了。但让坏事发生了。

但我想听听更多关于这方面的意见。


答案 1

我过去一直在你的案例中。我选择了神奇的方法。

这是一个错误,你问题的最后一部分说明了一切:

  • 这比 getters/setters
  • 没有自动完成(这实际上是一个主要问题),并且由IDE进行类型管理以进行重构和代码浏览(在Zend Studio / PhpStorm下,这可以使用phpdoc注释进行处理,但这需要维护它们:非常痛苦)@property
  • 文档(phpdoc)与代码的使用方式不匹配,查看您的类也不会带来太多答案。这是令人困惑的。
  • 在编辑后添加:为属性设置 getter 更符合“真实”方法,其中不仅返回私有属性,而且执行真实逻辑。您具有相同的命名。例如,您有(返回私有属性)和(计算)。当你的获取者得到的不仅仅是一个获取者并且需要做一些逻辑时,一切都是一致的。getXXX()$user->getName()$user->getToken($key)

最后,这是IMO最大的问题:这是魔术。魔法是非常非常糟糕的,因为你必须知道魔法是如何工作的才能正确使用它。这是我在团队中遇到的一个问题:每个人都必须了解魔力,而不仅仅是你。

Getters和setters写起来很痛苦(我讨厌他们),但他们是值得的。


答案 2

只有当物体确实是“魔法”时,您才需要使用魔法。如果你有一个具有固定属性的经典对象,那么使用 setter 和 getters,它们可以正常工作。

如果您的对象具有动态属性,例如它是数据库抽象层的一部分,并且其参数是在运行时设置的,那么为了方便起见,您确实需要神奇的方法。


推荐