PHP Ultimate Getter Setter Methods

PHP doesn’t offer much in the way of read-only member variables, so when you need one, you have to make the variable private, and define a getter method. This is all well and good, but what if your class has dozens of member variables? The class size grows quite quickly.

To solve this, I’ve written setter/getter methods that are all-purpose. You can use them to access all the variables in your class. Here’s a sample class that employs them:

class MyClass{
	// Member variable visibility
	private $readonly = array('myVar');
	private $noaccess = array('foo');
 
	private $myVar = true;
	private $foo = 'Hello';
	private $bar = '';
 
	/**
	* __construct()
	*	Description:
	*		Object constructor. 
	*	Parameters:
	*		none
	*	Returns:
	*		void
	**/
	public function __construct(){}
 
	/**
	* __set()
	*	Description:
	*		Setter method for class variables.
	*	Parameters:
	*		$key - the member variable name.
	*		$value - the new value.
	*	Returns:
	*		void	
	**/
	private function __set($key, $value){
		// Check to see the member variable exists in this class.
		if (array_key_exists($key, get_class_vars(__CLASS__))){
			// The member variable exists.
 
			// Check to see if the variable is read only.
			if (! in_array($key, $this->readonly)){
				/* This is where the variable gets   
				set. If any code needs to get executed 
                                when the variable is set, do it here. */			
				switch ($key){
					case 'bar':
					  $this->$key = strtoupper($value);
					  break;
					default:
					  // Other variables are set this way.
					  $this->$key = $value;
				}
 
			}else{
				// The variable is read only.
				throw new Exception('Variable is read only');
			}
		}else{
			// The variable does not exist.
			throw new Exception('Variable does not exist.');
		}
	}
 
	/**
	* __get()
	*	Description:
	*		Getter method for class variables.
	*	Parameters:
	*		$key - the member variable name.
	*	Returns:
	*		mixed - the value of the member variable requested.
	**/
	private function __get($key){
		// Check to see that the member variable exists.
		if (array_key_exists($key, get_class_vars(__CLASS__))){
			// The member variable exists, see if it's visible.
			if (!in_array($key, $this->noaccess)){
				return $this->$key;
			}else{
				throw new Exception('Variable is private');
			}
		}else{
			throw new Exception('Variable does not exist.');
		}
 
	}
 
	/**
	* hello_world()
	*	Description:
	*		Guess...
	*	Parameters:
	*		none.
	*	Returns:
	*		void.
	**/
	public function hello_world(){
		echo $this->foo . ' ' . $this->bar;
	}
}

It might look a bit complicated, but the idea is really simple once you understand PHP’s __get() and __set() magic functions. These functions are called whenever a member variable is accessed. This allows you to write code that gets executed each time this happens.

In the __get() example above, I check to see if the variable name passed in actually exists in the class, and if it does, I check to see if it’s in the $noaccess array. If the variable is in the $noaccess array, then an exception is thrown stating that the variable isn’t accessible, otherwise, the value is returned.

In the __set() example, I also check to see if the variable name passed is in the class, and if it is, I check to see if it’s in the $readonly array. If it is, an exception is thrown saying the variable is read-only. If the variable is not read-only, then the variable is set.

The __set() function also allows you to modify what happens when setting a variable. In the example above, when the variable $bar is assigned a value, the __set() function is instructed to convert the value to uppercase before storing it. All other variables are stored as is.

I’ve only just written these functions, and I haven’t used them enough to find any short-comings. If you use this code, or modify it to suit your needs, please give me credit, and let me know what you’ve done. I’m always interested to see how my code is being used.

Happy coding!

Links for the Week Ending February 24, 2008
Tags: , , , , , , , , , , , , , , ,
Daily Delicious for Wordpress

For those of you who are regulars of my site, you may have noticed some posts (mainly in your RSS feeds) that were blank. A major pain, I know. Well, this should be fixed now. I was troubleshooting a new Perl script that integrated del.icio.us into my site.

The Perl script I was working on automatically posts daily round-ups of links I post to del.icio.us on my Wordpress blog. I didn’t write the script from scratch, I made improvements to a script that’s been around for a while. I got it from edward.de.leau.net. There were a couple of drawbacks to the original script that I was working to correct. That’s where the hiccups on this site were coming from.

In order to use this script, you need an account with del.icio.us, and a server that allows you to schedule cron jobs. You need to schedule it to run just before midnight GMT (I chose 19:50 AST because my server is set to the AST timezone).

It will log into your del.icio.us account and get all the links you posted that day, and insert a post directly into your Wordpress database. It does NOT use an API to do this, it accesses the database directly. Use it at your own risk.

Link: Daily del.icio.us for Wordpress 3.0

Links for February 17, 2008
Tags: , , , , , , ,
SQLite Boolean — True or False?

For the past few months I’ve been working on a desktop application for a client that required a version for Mac and one for PC. I chose to write it using REALBasic 2007 because I don’t particularly like Java, and REALBasic allowed me to write source code once, and compile for OS X, Windows, and Linux which was a great time-saver.

My application had need of a database, and because of certain business requirements, a database server was out of the question. This left SQLite, a database engine that is compiled into the application itself, requiring only a data file to hold the database (SQLite also allows you to use an in-memory database by the way).

I guess I really should have read up on SQLite, but I didn’t. I just assumed it would function more or less like any other database. Well, there are a few annoying characteristics of SQLite that I hope get resolved in the near future. One is weak data-typing: I wrote the SQL script using integer, varchar, and boolean data types. This appeared to work at first, but then I noticed that I could store any string in a field of any type. This makes data corruption almost a certainty at some point.

I knew that I was going to be the only one writing code that accessed this database though, so I figured I could avoid this pitfall by being careful. I proceeded. I guess I wasn’t careful enough. I was having problems with booleans. I tried a statement to insert a boolean value into a table like this

INSERT INTO myTable (boolField) VALUES(true);

This caused a syntax error because of the symbol “true”. Ok, maybe I have to quote true.

INSERT INTO myTable (boolField) VALUES('true');

This seemed to work fine. I check the database using SQLiteManager from SQLabs, and see that the field does indeed hold the value true. Because of this apparent success I carry on writing code that uses ‘true’ and ‘false’ for booleans. Well, remember that SQLite is weakly typed. I had a field declared as a boolean, but I can store any old text in there. SQLite doesn’t care much.

It wasn’t until I stared editing boolean fields in SQLiteManager that I noticed ‘true’ was being stored as 1 and ‘false’ as 0. What a pain in the ass this is. I have to change all the code that interacts with booleans. If I have a boolean variable in my code, I need to make sure it gets cast as an integer before being inserted into the database, or I’ll get an error when I retrieve it and try to use it as a boolean. Oh, and in REALBasic, there is no way to cast a boolean as an integer, so I have to write a function to do it.

I wonder if there’s a better solution than SQLite out there. I’ve been spoiled developing web applications for so long. The logistics of a remote database server aren’t a problem, so I’ve always used Oracle, MySQL and MS SQL Server up until now.

Tags: , , ,