SitePoint Sponsor

User Tag List

Results 1 to 14 of 14
  1. #1
    Non-Member
    Join Date
    Jan 2004
    Location
    Los Angeles
    Posts
    103
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Loading Data into Classes

    Hey people
    Just a question regarding performace/good practice.

    Lets say I have a class and I want to set some data. From what I've read the way to do that is to have set/gets for each piece of data.

    $obj->set_var1()
    $obj->set_var2()
    $obj->set_var3() etc.....

    If you have alot of data that gets messy and its also a performance hit for each method call in a class.

    Another thought is to pass the data as an array:

    $obj->set_vars(array(
    'var1' => 454,
    'var2' => 642,
    'var3' => 234
    );

    or another thought is to load it into the function call

    $obj->set_vars($var1, $var2, $var3);

    anyone have any thoughts on why one is a better way than another?

    thanks

  2. #2
    SitePoint Evangelist
    Join Date
    Dec 2003
    Location
    Arizona
    Posts
    411
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Another method would be to use an associative array to store class vars:

    PHP Code:
    class MyClass {
        var 
    $vars = array();

        function 
    setVar($name$value) {
            
    $this->vars[$name] = $value;
        }

        function 
    getVar($name) {
            return 
    $this->vars[$name];
        }

    I prefer this method for classes with a variable number of parameters. Otherwise I usually go with the standard setUsername, setPassword type methods.

    JT

  3. #3
    Non-Member
    Join Date
    Jan 2004
    Location
    Los Angeles
    Posts
    103
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm more looking for which method is the most beneficial from a performance/good practice design.

  4. #4
    SitePoint Addict
    Join Date
    May 2003
    Location
    Auckland
    Posts
    309
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well it depends.

    If you need to set all the values at once then you could have the full var list in your method.

    Code:
     class TestClass {
       public SetAll($var1, $var2, $var$) {
     	$this->var1 = $var1;
     	$this->var2 = $var2;
     	$this->var3 = $var3;
       }
     }
    But you need to have methods for each var since if you only want to change an individual var.

    For example, if you wanted to change the value of var2, you wouldnt want to have to supply the full list of values for every single var in your class again, you'd just use the set method for that individual var.

  5. #5
    SitePoint Evangelist
    Join Date
    Dec 2003
    Location
    Arizona
    Posts
    411
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by recchi_8
    I'm more looking for which method is the most beneficial from a performance/good practice design.
    Well, if you created an associative array with the parameters and passed in a reference to it, you could do it in one function call with less overhead, so I would think that would be preferred over passing them all in by value. Performance-wise...

    JT

  6. #6
    Non-Member
    Join Date
    Jan 2004
    Location
    Los Angeles
    Posts
    103
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by seratonin
    Well, if you created an associative array with the parameters and passed in a reference to it, you could do it in one function call with less overhead, so I would think that would be preferred over passing them all in by value. Performance-wise...

    JT
    maybe do this....
    <?php
    function set_data(&$var1, &$var2)
    {
    $this->var1 =& $var1;
    $this->var2 =& $var2;

    }
    ?>
    for all my data I know HAS to be in the class

    and maybe a set_variable_data function where I can just pass in an array

  7. #7
    ********* Victim lastcraft's Avatar
    Join Date
    Apr 2003
    Location
    London
    Posts
    2,423
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Hi...

    Quote Originally Posted by recchi_8
    If you have alot of data that gets messy and its also a performance hit for each method call in a class.
    Do whatever is conceptually correct. Stuff should be bundled into a list if you have a variable number of items. Stuff should be bundled into a hash if you want to merge data or you are reading a source that generates key/value pairs. If you want to pass something complicated I would use an object.

    If after all of that you still have lot's of parameters then the chances are that your class is too big. See if you can break it down into smaller classes.

    There is an atomiticity constraint here as well. If partial data makes no sense, then it should all be set in one function call and that call should probably be the constructor.

    Worrying about performance at this stage is seriously counter productive . The following things will swamp an extra method call: reading the PHP file, parsing the PHP file, opening and closing files, network calls, database calls and shelling out to the command line. You should not try to optimise things you cannot even measure at the application level. You want to do this once at the beginning as a back-of-envelope calculation to see if things are feasible, and once at the end when you have something you can measure.

    Optimise for development time, this time is precious.

    yours, Marcus
    Marcus Baker
    Testing: SimpleTest, Cgreen, Fakemail
    Other: Phemto dependency injector
    Books: PHP in Action, 97 things

  8. #8
    Non-Member
    Join Date
    Jan 2004
    Location
    Los Angeles
    Posts
    103
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    thanks Marcus
    I appreciate the answer.

    Basically what I'm doing is showing form elements to an html page. There are several select boxes and I have to pre-populate them with Session data but they can be overwritten by POST data so I need to
    set several SESSION vars and several POST vars.

    It will probably turn out to be 5-7 session vars and the same for post.

    Then I have another class to display the graphing data.

  9. #9
    SitePoint Member
    Join Date
    Dec 2003
    Location
    ---
    Posts
    22
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi!

    You should do this. I choosed this approach because I have some class, which have a lot of member, and I was lazy to write a lot of get, set method.

    PHP Code:
        class {
            var 
    $_var1;
            var 
    $_var2;
            var 
    $_var3;
            var 
    $_var4;
            var 
    $_directAccessibleVars = array('var1''var2''var4');

            function 
    getVar2() {...}

            function 
    setVar($name$value true)
            {
                if (isset(
    $this->{'_'.$name})) {
                    if (
    in_array($name$this->_directAccessibleVars)) {
                        if (
    method_exists($this'set'.ucfirst($name))) {
                            
    $this->{'set'.ucfirst($name)}($value);
                        } else {
                            
    $this->{'_'.$name} = $value;
                        }
                    } else {
                        
    trigger_error('Member variable: '.$name.' can not set directly in '.__CLASS__.'::'.__FUNCTION__.'()!'E_USER_WARNING);
                    }
                } else {
                    
    trigger_error('Nonexistent member variable: '.$name.' in '.__CLASS__.'::'.__FUNCTION__.'()!'E_USER_WARNING);
                }
            }

            function 
    getVar($name)
            {
                if (isset(
    $this->{'_'.$name})) {
                    if (
    in_array($name$this->_directAccessibleVars)) {
                        if (
    method_exists($this'get'.ucfirst($name))) {
                            return 
    $this->{'get'.ucfirst($name)}();
                        } else {
                            return 
    $this->{'_'.$name};
                        }
                    } else {
                        
    trigger_error('Member variable: '.$name.' can not access directly in '.__CLASS__.'::'.__FUNCTION__.'()!'E_USER_WARNING);
                    }
                } else {
                    
    trigger_error('Nonexistent member variable: '.$name.' in '.__CLASS__.'::'.__FUNCTION__.'()!'E_USER_WARNING);
                }
            }
        } 
    FelhoBacsi

  10. #10
    SitePoint Guru
    Join Date
    Dec 2003
    Location
    oz
    Posts
    819
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Excellent way to emulate the private and public methods concept of proper OOP (which php doesnt have).

    Unfortunantly, you can't do anything with the getting/setting of particular variables

    Like if you want to store a particular string variable encrypted and unencrypt it when using the getter method - ie hiding the encryption from the user of the class - you cant do this due to the genericity of the method.

    Still like the way you worked around the lack of private vars in php4!

  11. #11
    SitePoint Member
    Join Date
    Dec 2003
    Location
    ---
    Posts
    22
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi!

    I found that using
    var $_directAccessibleVars = array('var1', 'var2', 'var4');
    is difficult to handle when you extend your class.
    So maybe using name convention, is a better way.
    I use _ prefix for all of my private variable, but for those I would like to allowe for setVar, getVar I could use _i_.
    I come from initiable, because the idea come from when I would like to allow to set the objects varaibles with one array as an argument of the constructor.

    Felho

  12. #12
    SitePoint Member
    Join Date
    Dec 2003
    Location
    ---
    Posts
    22
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi!

    I found a bug, the function won't work, if the variable was not initialized befor the call. So instead of using isset(), I check if the variable exists in the return of the get_class_vars. Note, that before php 4.2 this won't return the varaible which was not initialzed.

    So the new version is this.

    PHP Code:
    <?
        
    class {
            var 
    $_var1_i;
            var 
    $_var2_i;
            var 
    $_var3;
            var 
    $_var4;

            function 
    setVars($vars)
            {
                if (
    is_array($vars)) {
                    
    $objVars array_keys(get_class_vars(get_class($this)));
                    foreach(
    $vars as $varName => $value) {
                        
    // Instead array(..., array('isFrozen' => true), ...)
                        // you can use array(..., 'isFrozen', ...)
                        
    if (is_int($varName)) {
                            
    $varName $value;
                            
    $value true;
                        }
                        
    $this->setVar($varName$value$objVars);
                    }
                }
            }

            function 
    setVar($name$value$objVars null)
            {
                if (
    $objVars === null) {
                    
    $objVars array_keys(get_class_vars(get_class($this)));
                }
                if (
    in_array('_'.$name$objVars)) {
                    
    trigger_error('Member variable: '.$name.' can not set directly in '.__CLASS__.'::'.__FUNCTION__.'()!'E_USER_WARNING);
                } elseif (
    in_array('_'.$name.'_i'$objVars)) {
                    if (
    method_exists($this'set'.ucfirst($name))) {
                        
    $this->{'set'.ucfirst($name)}($value);
                    } else {
                        
    $this->{'_'.$name.'_i'} = $value;
                    }
                } else {
                    
    trigger_error('Nonexistent member variable: '.$name.' in '.__CLASS__.'::'.__FUNCTION__.'()!'E_USER_WARNING);
                }
            }

            function 
    getVar($name$objVars null)
            {
                if (
    $objVars === null) {
                    
    $objVars get_class_vars(get_class($this));
                }
                if (
    in_array('_'.$name$objVars)) {
                    
    trigger_error('Member variable: '.$name.' can not set directly in '.__CLASS__.'::'.__FUNCTION__.'()!'E_USER_WARNING);
                } elseif (
    in_array('_'.$name.'_i'$objVars)) {
                    if (
    method_exists($this'set'.ucfirst($name))) {
                        return 
    $this->{'get'.ucfirst($name)}();
                    } else {
                        return 
    $this->{'_'.$name.'_i'};
                    }
                } else {
                    
    trigger_error('Nonexistent member variable: '.$name.' in '.__CLASS__.'::'.__FUNCTION__.'()!'E_USER_WARNING);
                }
            }
        }
    ?>
    Felho

  13. #13
    SitePoint Guru
    Join Date
    Dec 2003
    Location
    oz
    Posts
    819
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hmm .. I'm just thinking that making every variable private forces you to have getter ad setter methods for every class variable - which is generally good OO practice.

    I think I'll do that from now on, since usually I'm too lazy and just get and set variables directly - which is a bad habbit

  14. #14
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by lazy_yogi
    I think I'll do that from now on, since usually I'm too lazy and just get and set variables directly
    At least it looks like you chose the right user name
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •