Keeping Superglobals Out Of Classes

« »

Have you ever written code like this?

<?php

class VerifyLogin extends UserObject
{
	function verifyCredentials()
	{
		$username = mysql_real_escape_string($_POST&#91;'username'&#93;);
		$password  = mysql_real_escape_string($_POST&#91;'password'&#93;);
		$passwordhash = MD5($username . $password); // Salt our PW Hash
		$sql = 'SELECT id FROM userTable WHERE username = ' . $username . ' AND password = ' . $passwordhash . ' LIMIT 1';

		$resource = mysql_query($sql);
		
		if(mysql_numrows($resource) > 0)
		{
			$array = mysql_fetch_row($resource);
			$this->userID = $array[0];
			$this->loggedIn = true;
			return true;
		}
		else
			return false;
	}
}

?>

The problem here ought to be clear: we’re using a class exactly like we would in some procedural code. This is a problem.

Let’s ignore the security implications of the above code for just a moment, and focus on just the use of the superglobal. By using the $_POST superglobal array, we’re effectively doing two things:

  1. We rely on our form fields always being called ‘username’ and ‘password,’ and our class breaks if they’re not.
  2. This object cannot ever be used for processing any other types of data, limiting code reuse.

This isn’t what objects are for. Objects are designed to take data and hold it, then act on that data. For example, our user object should information about that user. You might have methods that can act on that user, like promoting them to administrator or verifying their login credentials. In the latter case, you would need to take $_POST data but it would be much better to pass it in directly than to rely on the superglobal inside the object itself.

A better code snippet from a user object would look something like this:

<?php

class VerifyLogin extends UserObject
{
	function verifyCredentials($username,$password)
	{
		$username = mysql_real_escape_string($username);
		$password  = mysql_real_escape_string($password);
		$passwordhash = MD5($username . $password); // Salt our PW Hash
		$sql = 'SELECT id FROM userTable WHERE username = ' . $username . ' AND password = ' . $passwordhash . ' LIMIT 1';

		$resource = mysql_query($sql);
		
		if(mysql_numrows($resource) > 0)
		{
			$array = mysql_fetch_row($resource);
			$this->userID = $array[0];
			$this->loggedIn = true;
			return true;
		}
		else
			return false;
	}
}

?>

In this example, we get to select where the $username and $password variables come from. Likely they’ll come from a posted form, but we have the ability to determine that for ourselves. This class is much better, because it is a true blueprint of an object.

There are some legitimate uses of superglobals in classes. One example is the use of the $_SESSION superglobal, which is often used for things like a user object. But I urge you to do so sparingly, when appropriate, rather than relying heavily on superglobals which are subject to change and may not give you the data you expect.

Brandon Savage is the author of Mastering Object Oriented PHP and Practical Design Patterns in PHP

Posted on 12/15/2008 at 1:41 pm
Categories: Usability, Web Architecture, Best Practices
Tags: , ,

There are currently no comments.

« »

Copyright © 2023 by Brandon Savage. All rights reserved.