PHP5.3 and Namespaces

1 08 2010

In today’s post, I’d like to explore namespaces in PHP, a new feature that is in version PHP5.3. In particular, I will address the following two questions which arose during the course of a presentation that I made recently:

1) How can you switch from working in a particular namespace to the global space in a file?

2) How can you work with superglobals such as $_GET or $_POST with namespaces?

Before preceding, let’s deepen our understanding of namespaces. An oft cited analogy for PHP’s namespaces is the file directory structure on your computer where you have subdirectories or folders. Just as you may have more than one file with the same name and extension as long as it is in a separate subdirectory, so too you can carve out the global namespace in PHP and have classes with the same name, each being in a different namespace.

The online manual states that creating a namespace merely involves issuing a statement consisting of the keyword namespace followed by a name. Everything following that statement will be contained within that namespace. Actually, only functions, classes, CONSTANTs, and variables referring to any of these three features will comprise the namespace, as you will note from the example below.

namespace testing\ns\stuff\tonight {
$foo = 'fiddledefoo';
class bar {}
$b = new bar();
echo '<b>NAMESPACE: ' . __NAMESPACE__ . '</b>';
var_dump($b,$foo);
echo '<p></p>';
}
namespace {	
class bar{}
$b = new bar();	
echo '<b>NAMESPACE: (global)' . __NAMESPACE__ . '</b>';	
var_dump($b,$foo);
}

The code above does several interesting things. First, it shows how to work with a specific namespace and then change to the global namespace, answering one of aforementioned questions. Note how I move from working in the sub-leveled namespace to the global by means of applying curly braces to each defined namespace as delimiters. To indicate the global namespace, I use the namespace keyword without designating a name. According to the online manual, it is really inadvisable to write code like this . The preferred way is to put each namespace in its own file. If you wish, you may include that file in one containing code in the global scope.

By creating each namespace in a separate file, you can keep your code better organized and also eliminate any confusion that might result from having more than one namespace in a file. Also, each namespace is intended to rule the file containing its statement. This explains the reason, for example, that there must not be any html preceding a namespace declaration in a file, even though you may include that file in another one that does contain html above the included file.

The code also vividly illustrates that a variable appearing within a namespace may actually be global in scope. Take a look at $foo in \testing\ns\stuff\tonight. If $foo actually were a namespaced variable, then it should fail when I refer to it in the global namespace; the variable is equally available within the both the global and specified namespace. In contrast, there are two variables $b, one in the global space and one in \testing\ns\stuff\tonight and each refers to its own version of class bar.

The consequence of having two ore more classes with the same name residing in different namespaces does more than merely avoid naming conflicts. It also allows you to use PHP to effectively over-ride a method in a class, a feature that exists in Java but not PHP. You could do this in PHP with namespaces by selecting which class bar to use, as follows:

<?php
namespace some\ns {
class bar {
  private $data;
  function __construct() {
       $this->data = (int) $_GET['data'];
  }
  function showData() {
        return $this->data;
  }
  function changeData() {
        $this->data *= 2;
  }
 }
}
 

namespace {
	class bar {
		private $data;
		  function __construct() {
       		$this->data = (int) $_GET['data'];
  		   }
        	
			function showData() {
        		return $this->data;
  			}
  		function changeData() {
        	$this->data /= 2;
  		}
 	}

$choice = (int) $_GET['choice'];
$obj = null;

if ($choice == 1) {
   $classname = "some\\ns\\bar";
   $obj = new $classname;
}
else
if ($choice == 2)   {
         $obj = new bar;
}

echo "<P><strong>Data:</strong> ";
echo $obj->showData();
echo "<P>Let's change it ..<br />";
$obj->changeData();
echo "<p><strong>Result:</strong> ";
echo $obj->showData();
}
?>

This example answers the second question concerning using the superglobals in PHP with namespaces. As you can see, you may use $_GET (and other superglobals) without needing to exert any special effort, other than taking the usual security-related precautions.

The dynamic class instantiation of some\ns\bar may seem a little peculiar.  If you have any questions about that code, I refer you to a previous article that deals with this  subject in Dynamic Classes

Besides over-riding a class method, we can use namespaces to redefine built-in PHP functions. For example, here is an example where I create a prettier var_dump(), while at the same time incorporating PHP’s built-in into the revised function in test\ns\stuff\tonight. I also use the function in both the specified namespace as well as the global one, as follows:

namespace testing\ns\stuff\tonight {
	$foo = 'fiddledefoo';
	class bar {}
	$b = new bar();
	function var_dump($obj,$var) {
		echo '<pre style="padding:12;background:#ffffee;width:25%;border:1px solid black">';
		echo 'Var_dumping $b and $foo';
		\var_dump($obj,$var);
		echo '</pre>';
	}
	var_dump($b,$foo);
	echo '<p></p>';
}
namespace {	
	class bar{}
	$b = new bar();
	\testing\ns\stuff\tonight\var_dump($b,$foo);
}

Normally, you could end up with code problems if you tried to redefine a PHP built-in function. Using namespaces, allows one to have greater flexibility and create PHP more to your preference. Note, how I invoke PHP’s built-in var_dump() by referencing it as \var_dump(). If I had not redefined var_dump(), I could have also called it without a backslash in the sub-leveled namespace. When I move into the global space, I can still call my version of var_dump() by prefacing the function name with its fully qualified namespace name, ie \testing\ns\stuff\tonight.

Links of Interest
http://www.php.net/manual/en/language.namespaces.php
http://www.phparch.com/2010/03/29/namespaces-in-php/
http://www.sitepoint.com/blogs/2009/07/13/php-53-namespaces-basics/

This work is licensed under a Creative Commons License
.

Advertisements

Actions

Information

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




%d bloggers like this: