什么是存储PHP类属性的最佳方法?

5

重复问题: 什么是在PHP中存储类变量的最佳方式?

我和我的同事讨论了一段时间关于如何在PHP类中存储属性的问题。

那么你认为应该使用哪种方法呢?就像这样:

Class test{
    public $attr1;
    public $attr2;
    .............. 
    public function __construct(){
        $this->attr1 = val;  
        $this->attr1 = val;
        ...................   
    }
}

对比:

Class test{
    public $data;

    public function __construct(){
        $this->data['attr1'] = val;
        $this->data['attr2'] = val;
        ..........................       
    }
}

当您需要存储和检索具有许多属性的对象时,这一点非常重要。

在处理具有许多属性的对象时,是否为每个属性使用getter和setter,还是使用一个方法来设置所有属性和一个方法来获取所有属性,这也很重要?


这是一个好问题,但是是重复的。投票关闭。 - nickf
8个回答

9

版本1是更加“传统”的做法。你的对象就是你所描述的那样。

我不能说哪种方法严格来说“更好”,但我可以说哪种方法更方便。

我通常与自定义PHP5 getter和setter方法一起使用第二个版本(通常用于CodeIgniter中的数据库模型,特别是在早期开发中),以允许您动态地重载类。也就是说,

<?php
    class foo{
        private $data = array();

        function __construct()
        {
            # code...
        }

        public function __get($member) {
            if (isset($this->data[$member])) {
                return $this->data[$member];
            }
        }

        public function __set($member, $value) {
            // The ID of the dataset is read-only
            if ($member == "id") {
                return;
            }
            if (isset($this->data[$member])) {
                $this->data[$member] = $value;
            }
        }
    }

    $bar = new foo()
    $bar->propertyDoesntExist = "this is a test";
    echo $bar->propertyDoesntExist; //outputs "this is a test"
?>

你应该使用公共函数&__get($member),这样你就可以使用$class->someArray['key'] = 'value'; 这种方式,这样你也可以将数组存储为类属性。 - Pim Jager

5

如果数据来自于外部源(例如BD查询),我会仅在这种情况下使用第二个版本。当然,在这种情况下,建议使用通用的 __get()/__set() 方法来访问 $this->data。您还可以考虑实现 IteratorAggregate 接口 并返回 new ArrayIterator($this->data)


1

除非有相當有說服力的理由支持其中一種格式(取決於上下文),我總是選擇能讓我的IDE/工具更好地提供關於類型、類別、關係等信息的格式,而直到現在這還是第一種格式。
還有其他訪問數據“類似數組”的方式。


1

第一种方法非常标准。它清楚地定义了属性,允许IDE和代码文档工具捕捉到可用的对象属性。

第二种方法非常适合需要将数据保留在单独范围内的受保护和私有级别属性。我在各种模型类中使用两种方法的组合,或者跟踪配置选项和默认值。但是,我总是会预先填充这些数组,并确保严格遵守其中的数据。

我绝不会为公共属性使用第二种方法,因为这表明缺乏对对象属性和变量作用域的理解,并可能在代码中引入问题(如果有人用字符串覆盖根数组怎么办?)

使用getter和setter对需要向调用代码进行更改的属性很有意义。并非每个属性都应该是可访问的,因此由开发人员定义对象。显然,getter/setter模式对于公共属性没有意义,但对于需要进行某些验证或进行消毒的受保护和私有属性有意义。它们也在依赖注入的上下文中有意义。


0

最好的方法肯定是标准方法,但第二种方法肯定更加舒适...

我使用第一种方法,并在类内部使用此函数以实现动态工作:

    public function GET__Attributes_in_Array(){
     $Prova = get_class_vars(get_class($this));
     print_r($Prova);

     return $Prova;
}

这个函数会返回一个包含类的所有属性和值的数组...


0

个人而言,我使用版本1,因为我认为它更正确,在IDE中支持自动完成,并使调试更容易。

我几乎为所有成员变量使用getter和setter(大多数情况下我定义为私有/受保护),因为设置一个值经常会触发其他值的更改。创建getter和setter的一个缺点是,如果您为不触发其他地方更改的属性定义getter/setter,则会积累大量丑陋、愚蠢的代码。我仍然这样做是为了保持一致的接口-我永远不知道何时会引入额外的功能或修复引入更多的更改-on-set。


这正是我对于 getters 和 setters 的问题所在,它们生成大量大多数无用的代码... - Brayn
@Bryan:如果是这样的话,你可能应该回到过程化编码 ;) - Mario Mueller

0
我也更喜欢版本1。如果您不需要动态成员(Chris提供的版本),则应该定义您的成员。动态方式在大多数情况下会导致可怕的结构,使得很难理解您的代码。想象一下,有人可能需要调试您的代码,但不知道您的代码^^。我们有一个使用动态成员来反映db表中字段的较大项目。如果不了解表格,则很难使用。
除了您的IDE无法使用dyn.成员外,您还不能为这些成员使用PHPDoc,并且PHPUnit无法在这些属性上使用Reflection。这只是糟糕的编码风格。
问候, 马里奥

0
使用版本1的原因是版本2发生在对象内部。您的对象已经是一个变量名到值的映射。通过添加自己的arraymap,您正在添加不必要的间接层级。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接