views:

1021

answers:

7

Duplicate of: http://stackoverflow.com/questions/546403/whats-the-best-way-to-store-class-variables-in-php

For some time I've been having this discussion with a co-worker on how should you store attributes within a PHP class.

So which one do you think it should be used. Something like this:

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

Versus:

Class test{
    public $data;

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

This is important when you have objects with many attributes that have to be stored and retrieved within often.

Also important when dealing with objects with many attributes, do you use getters and setters for each attribute or rather one method to set all and one method to get all ?

+5  A: 

I'd use second version if and only if the data comes as a whole from external source (e.g. BD query). In that case of course it'll be recommendable to have generic __get()/__set() to access $this->data. You might also consider implementing IteratorAggregate interface returning new ArrayIterator($this->data).

vartec
A: 

Unless there are really convincing arguments for either version (depnding on the context) I always chose the format the lets my ide/tools provide better information about the types, classes, relationships, ... and until now that's the first format.
There are other ways to access the data "array-like".

VolkerK
A: 

personally i use version 1, because i think it is more correct, supports auto-completion in IDEs and makes debugging easier.

i also use getters and setters for almost all of my member variables (which i define private/protected most of the time), because setting one value triggers changes in other values very often. one downside of creating g&s is the vast amount of ugly, stupid code that accumulates over time, if you define getters/setters even for attributes that do not trigger changes elsewhere. i still do it for the consistent interface - i never know when i introduce additional functionality or bugfixes that introduce more changes-on-set.

Schnalle
This is exactly my problem with getters and setters, it generates an extraordinary amount of mostly useless code...
Brayn
@Bryan: If so, you should probably go back to procedual code ;)
Mario Mueller
+3  A: 

Version 1 is the more "classical" way of doing things. Your object is pretty much exactly as you say it is.

I can't say which is strictly "better", but I can say which I find more convenient.

I've used the second version (usually for database models in CodeIgniter, and particularly during early development) in combination with custom PHP5 getter and setter methods to allow you to overload the class dynamically. i.e.

<?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"
?>
Chris
you should use public function That way you can store arrays as class attributes too.
Pim Jager
A: 

I would prefer version 1, too. If you do not need dynamic members (the version Chris provided), you should define your members. The dynamic way leads in most cases to a horrible construct that makes it hard to understand your code. Imagine, that somebody might need to debug your code and does not know your code ^^. We have a larger project that uses dynamic members to mirror the fields in the db table. Its pretty hard to use without knowing the table.

Beside the fact, that your IDE doesn't work with dyn. members, you cannot use PHPDoc for those members AND PHPUnit cannot use Reflection on those attributes. Thats simply bad coding style.

Regards, Mario

Mario Mueller
A: 

The first method is pretty much standard. It clearly defines what the properties are, and allows IDEs and code documentation tools to pick up on available object properties.

The second method is great for protected and private level properties in which you need to keep the data in a separate scope. I use a combination of both approaches in various model classes, or to track configuration options and defaults. I would always pre-fill these arrays, however, and ensure strict adherence to the data within.

I would not ever advocate using the second method for a public property, as it demonstrates a lack of understanding of object properties and variable scope, and can introduce problems in the code (what if someone overwrites that root array with a string?)

The use of getters and setters makes since on the properties that need to be changeable to the calling code. Not every property should be accessible, so it's up to the developer defining the object. The getter/setter pattern doesn't make sense with public properties, obviously, but it does with protected and private properties which may need some validation or to be sanitized. They also make sense in context of dependency injection.

Ryan Chouinard
A: 

The reason to use version 1 is that version 2 takes place within the object. Your object is already a map of varnames to values. By adding your own arraymap you are adding a needless level of indirection.

jmucchiello