Skip to main content

An easier way to assign instance variables

File under

Ever find yourself doing something like this?

$q = "SELECT * FROM person WHERE id=$id";
$r = mysql_query($q);
$row = mysql_fetch_array($r);

$this->id = $row['id'];
$this->firstName = $row['firstName'];
$this->lastName = $row['lastName'];
...
$this->pantSizeAfterThanksgiving = $row['pantSizeAfterThanksgiving'];

In other words: you have a class which has some instance variables, and you store those variables in a database. Then, in the constructor for that class, you grab the values from the database and set the variables one-by-one. It's a common pattern, which is part of what makes it such a bore to type out all those assignment statements.

Well, there's a better way. It isn't particularly clever, but often you won't see it mentioned in beginner-level OOP texts and articles because it somewhat obfuscates how you assign instance variables. At any rate, whenever you're doing some kind of repetitive action, you should always stop and say to yourself, "There has to be a better way", because if there's one thing that computers are good at, it's looping through repetitive tasks.

The next time you're in this situation, make the following adjustment (in bold):

...
$row = mysql_fetch_array($r, MYSQL_ASSOC);
foreach($row as $key=>$val)
  $this->$key = $val;

This is equivalent to the previous code snippet – mostly. A few caveats:

  1. You must use the MYSQL_ASSOC parameter
    This parameter tells PHP to return an associative array, and an associative array only. By default, mysql_fetch_array returns an array that has both associative and numeric indices. If you're used to assigning variables using the first method, you would never notice this. But if you loop through the array using foreach, you'll end up setting properties with names like '0', '1', and so on. You don't want that.
  2. Your instance variable names must match your column names
    Obviously, if you have a database column named first, but your instance variable for this data is named firstName, using foreach won't work. But even if you don't need to loop through your columns to assign instance vars, it's always good practice to give your column names and your instance vars the same names. There is simply no good reason to give them different names. It's confusing; it's error prone; it's more difficult; and it has no benefit. Don't do it.
  3. You have to want all the values in the database to be set as instance vars
    But then, if your model of this object includes a lot of crap that shouldn't be set in your instance vars, then maybe you need to redesign your model.

Notice how this strategy can easily be made to go the other way, when you're saving your instance vars back to the database. In PHP5, you can iterate over objects, too:

$person = new Person($id);
foreach($person as $key=>$val)
  echo $key . " => " . $val . "\n";

The above will print out all the instance vars in the person object, which could be pretty handy for dynamically building an INSERT or UPDATE statement. Of course, you should probably be using some kind of database class to handle all your database chores anyway, but if you're not, these methods should at least make things a bit easier.