Traditional Code and Magic Methods – What’s the Best Solution?

Posted on April 12, 2012 by

I recently had the pleasure of going through someone else’s code in order to make changes requested by the client. I was surprised to see so much “proper” code set up in there and realized how lucky I am to be using a more “practical” approach with magic methods.

Traditional Code: Getter and Setter Functions for Every Property

When in school they teach you to use setter and getter functions for each property within your class object. This is great, until you actually have to start working with it.

Imaging a class with 25 properties in it. That’s 50 functions in the class (25 set and 25 get methods) … just to add a value to a property, or get one from a property.

While there is nothing wrong with this approach, as a developer working on web applications I can tell you that the idea of having to code all these methods and then having to call each set to populate the property, and each get to get the value of the property is a pain. It would be much easier and more readable to do it directly: $person->first_name = “tom”; and print $person->first_name;

Magic Methods: One Method Mentality

PHP has blessed us with two magic methods: __set() and __get(). These let you decide how to handle populating and retrieving data.

In order to use them though you need to put all your properties into an array. This makes them inaccessible to the object. Why? because your object only has one property at the moment – the array – that’s it’s baby. It doesn’t consider the values in the array as anything worthwhile and ignores them.

Below is an example of a Person class with one private property – the array which stores a key/value pair of data (remember, the class doesn’t care about the data – just the array).

<?php
	class Person {
	   public $error           = false;
	  private $_arrProperties = array(
	                             'first_name' => '',
	                             'last_name'  => '',
	                             'email'      => ''
	                           );
	
	   public function __construct() {}
	
	} // end of Person Class
	?>

We’ll see how the public $error property comes into play later on. Now we’ll look at adding the __set and __get magic methods and see how they help us out.

Overloading Your Object – Making it Care about what’s in the Array

The __set() and __get() magic methods allow you to create properties within your object on the fly. This is called “overloading” your object because you are basically adding properties it wasn’t coded to handle, thus making the object work harder than it thought it was suppose to.

In our case, our class only has one property outside the $error property – the $_arrProperties array; but, we’re sneaky and we’ve actually put all our properties within this array. This allows us to use the __set() and __get() magic methods while still keeping the code readable and easy to understand.

<?php
	class Person {
	   public  $error          = false;
	  private $_arrProperties = array(
	                             'first_name' => '',
	                             'last_name'  => '',
	                             'email'      => ''
	                           );
	
	   public function __construct() {}
	
	   public function __set($name, $value) {
		  $this->error = true; // Anticipating a problem.
		  if (array_key_exists($name, $this->_arrProperties)) {
			 $this->_arrProperties[$name] = strip_tags(trim($value));
			 $this->error = false; // Nope - no problem.
			 return;
		  }
	   } // end of set
	
	   public function __get($name) {
		  $this->error = true; // Anticipating a problem
		  if (array_key_exists($name, $this->_arrProperties)) {
			 $this->error = false;
			 return $this->_arrProperties[$name];
		  }
	   } // end of __get
	} // end of Person Class
	?>

In the example above we’ve added our two magic methods. Below is how we call these methods:

<?php
	$person = new Person();
	
	$person->first_name    = 'Tom';
	$person->last_name     = 'Jones';
	$person->email        = 'tom.jones@example.com';
	
	print 'This is ' . $person->first_name . '.';
	
	$person->favorite_food = 'Pizza';
	if ($person->error) {
	   print "There is no favorite food property in the Person class.";
	}
	?>

In the example above it looks like we’re using public properties, but in reality all the properties don’t exist until we actually create them by overloading the Person class. Our __set and __get methods allow us to reduce the amount of code we need to write, while at the same time keeping our code readable and easy to follow.

Modelling a Data Table: Keeping Table Fields in the Properties Array

If you model your class against your database table, one great feature of this set up is that you can store the table fields as properties in the array and keep those properties which do not model your table out of that array.

This allows you to create easier SQL statements via a for loop, saving you the trouble of writing out all the fields and their new/modified values (if you’re binding values via PDO it’s a little trickier, but not by much).

For join tables you can have your class house a second array with the foreign keys associated with this record. When writing your SQL to update that join table all you’d need to do is loop through that array.

Keep Your Code Footprint Small, but Easy to Understand

When you code, the best thing you can do is to reduce the amount of lines you have to write while still keeping your logic easy to understand. PHP’s magic methods allows you to do just this.

Short, sweet and to the point – magic methods are a very helpful tool in your developer’s toolbox.