Php __get()和_set()的最佳实践

Php __get()和_set()的最佳实践,php,oop,magic-methods,Php,Oop,Magic Methods,基于使用\uuu get()和\uu set()访问私有变量,我想了解它们的一般用法。我想知道何时何地使用重载函数的最佳时机,以及您在哪里使用过重载函数(如果有) 为了清楚起见,我们正在讨论这些函数:一些示例: class formatedContainer { private $holder; protected $mode = "formated"; public function __set($var, $value) { $formated =

基于使用
\uuu get()
\uu set()
访问私有变量,我想了解它们的一般用法。我想知道何时何地使用重载函数的最佳时机,以及您在哪里使用过重载函数(如果有)

为了清楚起见,我们正在讨论这些函数:

一些示例:

class formatedContainer {
    private $holder;
    protected $mode = "formated";

    public function __set($var, $value) {
        $formated = chunk_split($value, 4, "-");
        if(substr($formated, -1) == "-") 
            $formated = substr($formated, 0, strlen($formated) - 1);
        $this->holder[$var] = array('formated' => $formated, 'plain' => $value);
    }

    public function __get($var) {
        return $this->holder[$var][$this->mode];
    }

    public function getPlain() {
        $this->mode = "plain";
    }

    public function getFormated() {
        $this->mode = "formated";
    }
}

$texts = new formatedContainer();
$texts->myText = md5(uniqid());
$texts->anotherText = md5("I don't change!");

//Prints something like: 440e-6816-b2f5-7aa5-9627-9cc8-26ef-ef3b
echo $texts->myText;

$texts->getPlain();

//Prints something like: 8559d37c5a02714dca8bd1ec50a4603a
echo "<br/>" . $texts->anotherText;
类格式化容器{
私人美元持有人;
受保护的$mode=“格式化”;
公共函数集($var,$value){
$formatted=chunk\u split($value,4,“-”);
if(substr($formatted,-1)=“-”)
$formatted=substr($formatted,0,strlen($formatted)-1);
$this->holder[$var]=array('formatted'=>$formatted,'plain'=>$value);
}
公共函数获取($var){
返回$this->holder[$var][$this->mode];
}
公共函数getPlain(){
$this->mode=“plain”;
}
公共函数getFormatted(){
$this->mode=“formatted”;
}
}
$text=新格式化的容器();
$text->myText=md5(uniqid());
$text->anotherText=md5(“我不改变!”);
//打印类似以下内容:440e-6816-b2f5-7aa5-9627-9cc8-26ef-ef3b
echo$text->myText;
$text->getPlain();
//打印类似于:8559d37c5a02714dca8bd1ec50a4603a的内容
回声“
”$文本->其他文本;
有点没用,但我想你会有主意的。}

我使用_get()和_set()访问私有数组的元素,即:

class Something {
    private $data;

    public function __set($key, $value) {
        //put validation here
        $this->data[$key] = $value;
    }

    public function __get($key) {
        if (!array_key_exists($this->data, $key)) {
             throw new Exception("Invalid member $key.");
        } else {
             return $this->data[$key];
        }
    }
}
因此,通过一些验证,像$person->age=“asdf”这样的东西会立即抛出一个异常(而如果age是一个公共成员就可以了)

此外,如果不希望类中存在任意“成员”,则可以在_set()中限制哪些键有效。

惰性模型getter(使用_get()) 我不记得在我的应用程序中经常使用PHP的神奇方法,但我记得有一种情况,
\uu get()
非常有用

早在我用CakePHP框架开发应用程序的时候,它有很多模型,并且在特定控制器中使用的所有模型都已初始化,即使该方法仅使用其中一个或两个(这就是Cake的工作方式)。所以我决定将其改为lazy模型(当第一次使用模型时加载模型)

我所做的只是添加了一个非常简单的
\uu get()
函数,该函数用于查找具有特定名称的模型并将其加载。这就像3-4行代码。我在AppController中定义了它(所有CakePHP类都源自该控制器),然后我的应用程序突然提高了速度并使用了较低的内存

后来我进一步研究了它,并以同样的方式加载了惰性组件

动态模型方法(使用_call()) CakePHP的另一个好例子是如何在模型上搜索蛋糕。基本上,每个模型都有两种方法:
find()
findAll()
,但也可以使用方法
findBy()
findAllBy()
进行搜索

在本例中,如果您有db表

notes(id, date, title, body)
并为此创建蛋糕模型。您可以使用诸如
findById()
findbytle()
等方法。您只需要CamelCase db字段,就可以更快地搜索任何字段


Cake是通过使用
\u call()
魔术方法来实现的。如果您试图执行一个不存在的方法,然后它只运行
find()
findAll()
,并根据方法名称和参数动态创建条件,则会调用此方法。这很容易实现,并且可以给您带来很多好处。

在Web上有很多示例,使用
\uuu get()
\uu set()
与私有“属性数组”结合使用。在我的类定义中,我希望有一个有趣的转折点,那就是能够真正声明公共属性,并且仍然使用这些神奇的拦截器——用于更多的自文档化代码,并使我的IDE能够完成代码编写等。通常,如果声明了这些属性,
\uu get()
\uu set()
将不会被调用。我发现,如果我
unset()
在我的类构造函数中使用相同的属性,我就可以两全其美。

你引用的页面标题中的“神奇方法”一词让我立刻产生怀疑。;)但是这个值比$person['age']这个常用用法高出多少呢?在_set()中,不仅可以像Jake说的那样限制允许哪些属性,还可以验证所设置的值。