"Conan is my role model." If I make that statement at the dinner table, my son would immediately think that I pattern myself after Conan the Barbarian, whereas my wife would think I want to be like the late-night talk show host, Conan O'Brien. This context confusion is known in IT as name collision. Many languages have a strategy to circumvent name collision and, with V5.3, so does PHP. PHP solves the name collision problem with its new namespaces feature. Of course, the names on which PHP resolves collision are not the names of people but rather the names of classes, functions, and constants.
This article explains why you should consider using namespaces on your next project. It provides an overview of namespace semantics, provides best practices, and offers a sample Model-View-Controller (MVC) application that uses namespaces. The article then discusses namespace support in Eclipse, NetBeans, and Zend Studio, with specific instructions on using namespaces with Eclipse.
A strength of the PHP language is its simplicity. So if you are new to PHP, namespaces are yet another concept you will need to understand. But if any of the following are true, you should consider their use:
- You are developing a large application with hundreds of PHP files.
- Your application is being developed by a team of coders.
- You are planning on using frameworks that use PHP V5.3 and namespaces.
- You have used namespaces (or comparable functionality, such as packages) in other languages, such as the Java™, Ruby, or Python languages.
If you are the sole developer of relatively small applications, namespaces may not be for you. But for the rest of us, namespaces provides a clean way to organize class structures and, of course, prevent name collision. These two reasons are why many framework developers are adopting the use of namespaces. Zend Framework (the 800-pound gorilla of PHP frameworks), for example, is using namespaces in Zend Framework V2.0.
A namespace provides a context for a name. For example, the two classes shown in Listing 1 have name collision.
Listing 1. Two classes with the same name cause collision without namespaces
class Conan {
var $bodyBuild = "extremely muscular";
var $birthDate = 'before history';
var $skill = 'fighting';
}
class Conan {
var $bodyBuild = "very skinny";
var $birthDate = '1963';
var $skill = 'comedy';
}
|
To specify a namespace, you simply add a namespace declaration as the first statement in the source, as shown in Listing 2.
Listing 2. Two classes of the same name but with namespaces resolves collision
<?php
namespace barbarian;
class Conan {
var $bodyBuild = "extremely muscular";
var $birthDate = 'before history';
var $skill = 'fighting';
}
namespace obrien;
class Conan {
var $bodyBuild = "very skinny";
var $birthDate = '1963';
var $skill = 'comedy';
}
$conan = new \barbarian\Conan();
assert('extremely muscular born: before history' ==
"$conan->bodyBuild born: $conan->birthDate");
$conan = new \obrien\Conan();
assert('very skinny born: 1963' == "$conan->bodyBuild born: $conan->birthDate");
?>
|
The above code runs fine, but before I describe why the two Conans work well together, let me point out two things. First, I'm using assertions to prove that the code works as expected. And second, I'm doing something you should never do: declaring multiple namespaces in one source file.
The namespace provides a unique qualifier for the two Conans. The code
clearly states when I'm referring to the burly destroyer or the late-night
talk show host. Notice that the syntax for the instantiation uses a
backslash (\) followed by the namespace name:
$conan = new \barbarian\Conan(); |
and:
$conan = new \obrien\Conan(); |
Those qualifiers kind of look like Windows®-style directory qualifiers, which is not a bad way to think about them because, for one, namespaces support both relative and absolute references (just like directories), and for another, it is a best practice to put the source for your class files in directories that match the namespaces.
It would be more real-world to separate the two Conan classes into directories called barbarian and obrien, and then reference those classes from other PHP files. There are three ways to reference a PHP namespace:
- Prefix the class name with the namespace
- Import the namespace
- Alias the namespace
To use the first option, you simply prefix the class name with the namespace (after, of course, you the include the source file):
include "barbarian/Conan.php"; $conan = new \barbarian\Conan(); |
That's pretty straightforward, but the issue with option one's strategy is that, given a large application, you will be constantly retyping the namespace. And besides all that typing, you are needlessly cluttering up your code base. With option two, you import the namespace with the PHP V5.3 reserved word use:
include "barbarian/Conan.php"; use barbarian\Conan; $conan = new Conan(); |
Option three lets you specify an alias for the namespace:
include "barbarian/Conan.php"; use \barbarian\Conan as Cimmerian; $conan = new Cimmerian(); |
(Cimmerian, by the way, is yet another moniker Conan the Barbarian is known by.)
One issue I have with all three of the above examples is the use of the
include statement. You can remove the need
for the includes by using an __autoload function. The PHP magic method __autoload function is called whenever a class is
referenced that has not yet been included in the source file. Place the
code in Listing 3 in a file called autoload.php.
Listing 3. A magic
__autoload function dynamically includes source files
<?php
function __autoload($classname) {
$classname = ltrim($classname, '\\');
$filename = '';
$namespace = '';
if ($lastnspos = strripos($classname, '\\')) {
$namespace = substr($classname, 0, $lastnspos);
$classname = substr($classname, $lastnspos + 1);
$filename = str_replace('\\', '/', $namespace) . '/';
}
$filename .= str_replace('_', '/', $classname) . '.php';
require $filename;
}
?>
|
Then import autoload.php into your source:
require_once "autoload.php"; use \barbarian\Conan as Cimmerian; |
The big advantage of the auto-loader is that you won't have to create an
include statement for every class. Note that
although PHP's namespaces can be used for functions and constants as well
as classes, the auto-loader technique only works for classes. The
auto-loader is so handy that rather than coding functions, you can create
methods in a appropriately named utility class and put your constants in
immutable classes.
Leaving O'Brien to ridicule The Destroyer while being slain, let's move on to a simple example MVC application. To benefit from namespaces, you should design your naming conventions before keying a line of code. A common best practice is to use a namespace tree. Understand that namespaces have high-level namespaces and sub-namespaces. If your company has multiple applications, it might be handy to have a high-level namespace that is your company name. Then, you would use a sub-namespace for the application. Next, you'd have a level that contains directories that in turn have names that specify the application functionality of the PHP classes contained therein. For example, let's say the high-level company namespace is denoncourt, the first sub-level is retail, and the third level has functional names, as shown in Listing 4.
Listing 4. A design for namespaces can include nested sub-namespaces
/denoncourt /retail /common /controller /model /utility /view |
The controller,
model, and view
sub-namespaces are obviously for the MVC architecture, but the
utility and common
sub-namespaces I threw in to be used for general classes that didn't
cleanly fit in one of the other sub-namespaces.
Let's jump right into the code for the mini-MVC application. Listing 5 provides the code for index.php, which is placed in the root folder.
Listing 5. The MVC application's index PHP uses the controller class
<?php require "autoload.php"; use denoncourt\retail\controller as Control; $controller = new Control\Controller(); $controller->execute(); ?> |
Notice the long namespace and the use of the alias name of
Control. The use of aliases is my preferred
method for using namespaces for two reasons: First, if I later rename the
namespace, I only have one line of code to change per source file. And
second, given that it is a best practice to fully qualify your namespace
as you instance classes, my use of
Control\Controller() is effectively the same
thing as
\denoncourt\retail\controller\Controller().
Note that I could have just as well created an alias for a higher-level
namespace, and then used the names of the sub-namespace for the class
instantiation:
use denoncourt\retail as Retail; $controller = new retail\controller\Controller(); |
This is a handy feature for those times when you will be referring to multiple levels of your namespace in the same source file. In the denoncourt/retail/controller directory, I created Controller.php, which is shown in Listing 6.
Listing 6. The MVC controller class predicates action based on user input
<?php
namespace denoncourt\retail\controller;
use denoncourt\retail as retail;
class Controller {
public function execute() {
switch ($_GET['action']) {
case 'showItem' :
$item = new retail\model\Item();
require "denoncourt/retail/utils/format.php";
require "denoncourt/retail/view/item.php";
break;
}
}
}
?>
|
In denoncourt/retail/model, I created Item.php. Listing 7 shows the code.
Listing 7. The MVC Item class is in the model sub-namespace
<?php
namespace denoncourt\retail\model;
class Item {
public $itemNo = '123';
public $price = 2.45;
public $qtyOnHand = 87;
}
?>
|
In denoncourt/retail/utils, I created format.php, which is shown Listing 8.
Listing 8. The dollar PHP shows how a function can also be namespaced
<?php
namespace denoncourt\retail;
function dollar($dollar) {
return "\$$dollar";
}
?>
|
Note that, as stated earlier, I would have preferred to put the format function in a utility class (so the auto-loader would handle the import of the code and I wouldn't have had to code the require statement for format.php).
Finally, the item.php view page is in denoncourt/retail/views. Listing 9 shows the code.
Listing 9. The item page displays the model instanced in the controller
<html>
<head>
<style>
dt {
float:left; clear:left;
font-weight:bold;
margin-right:10px;
width:15%;
text-align: right;
}
dd { text-align:left; }
</style>
</head>
<body>
<dl>
<dt>Item No:</dt><dd><?php echo "$item->itemNo"; ?></dd>
<dt>Price:</dt><dd>
<?php echo \denoncourt\retail\dollar($item->price); ?>
</dd>
<dt>Quantity On Hand:</dt><dd><?php echo "$item->qtyOnHand"; ?></dd>
</dl>
</body>
</html>
|
Notice how the item page qualifies the dollar
function with \denoncourt\retail\ namespace.
If a source file has a namespace declaration, then all references to
classes, functions, and constants use the namespace semantics. When PHP
encounters an unqualified class, function, or constant, it does what is
know as fallback. A fallback on a user class causes the compiler
to assume the current namespace. To refer to non-namespaced classes, you
need to put a lone backslash. For example, to refer to PHP
Exception class, you would use $error = new \Exception();. Keep that in mind as you use any of the Standard PHP Library classes (such
as ArrayObject,
FindFile, and
KeyFilter).
For functions and constants, if the current namespace does not contain that
function or constant, PHP's fallback mechanism will fall back to the
standard PHP function. So, for example, if you've coded your own strlen function, PHP would resolve to your
function. But, if you also wanted to use the standard PHP strlen function (say, within your own strlen implementation), you'd need to precede the
function invocation with a backslash, as Listing 10 shows.
Listing 10. PHP standard functions can be qualified with a backslash to identify the global namespace
<?php
namespace denoncourt\retail;
function strlen($str) {
return \strlen();
}
?>
|
The namespace global variable and strings
If you like to code dynamic methods, you may be tempted to place a
namespace in a double-quoted string: "denoncourt\retail\controller". But
remember that you'll need to escape those slashes:
"denoncourt\\retail\\controller". One workaround is simply to use single
quotation marks: 'denoncourt\retail\controller'.
As you do your dynamic programming, keep in mind that PHP V5.3 has a new
global variable called __NAMESPACE__. Consider
using the global variable rather than typing it:
$echo 'I am using this namespace:'.__NAMESPACE__; |
Most of the major IDEs already have support for PHP V5.3. NetBeans V6.8 has great support for namespaces. Not only does it have code completion but it also makes suggestions for improving your code with best practices. For example, it is a best practice with PHP namespaces to fully qualify your namespaces within your code using with absolute references rather than relative references. If you key code that uses relative namespace qualifiers, NetBeans displays a light bulb icon in the left-most code margin. If you hover over the icon, NetBeans shows a tool tip describing the suggested change. And if you then click the icon, NetBeans makes the code change for you.
Zend Studio provides similar capabilities. If you are reticent to begin using namespaces, consider upgrading your IDE and try out namespaces with a bit of help from your favorite IDE. Note that you may find that you don't even have to upgrade your IDE, as many of them have provided PHP V5.3 features for more than a year now.
PHP Development Tools (PDT) V2.1 also has solid support for namespaces. PDT is a plug-in for Eclipse. A link to the installation notes for PDT is provided in the Resources section.
To enable namespace support, I first had to tell Eclipse/PDT to use PHP V5.3. To do that, from the application main menu, click Window > Preferences, as Figure 1 shows. Expand PHP in the tree pane, then choose PHP Interpreter. Then, change the PHP version to PHP 5.3, and click OK.
Figure 1. The Eclipse PDT plug-in requires you to set the interpreter to PHP V5.3
You can create a PHP project by clicking File > New
Project, expanding the PHP node, and then clicking
PHP Project. To create a PHP file, simply right-click
the project in PHP Explorer, then click PHP file. PDT
uses appropriate syntax highlighting for the namespace keywords of
namespace and use
(see Figure 2).
Figure 2. PDT uses syntax highlighting for namespace keywords and displays namespaces in the PHP Explorer and Outline views
It's handy to have PDT show you the namespaces in the PHP Explorer and
Outline views, as it helps you visualize how your namespaces are assigned
to various classes. PDT also provides something we've come to expect with
IDEs: code completion (see Figure 3). Code completion
is invoked by PHP while keying the use
statement.
Figure 3. PDT provides code completion for namespaces
PDT will also pop up a code completion window while you key class names.
For example, if I type new Item, PDT will also
show a window listing Item �
denoncourt\retail\item.
When I select denoncourt\retail\item, PDT inserts the required use statement and the qualifier on the instantiation line:
use denoncourt\retail\model; new model\Item(); |
What's cool is when I type new Conan, PDT also shows a window listing:
Conan � obrien Conan � barbarian |
Allowing me to select the appropriate Conan. And now that I've wandered back to my infatuation with the two Conans, perhaps it is time to wrap things up.
If you are still hesitant to get started with namespaces, before you put off learning namespaces for another year, I suggest you load your favorite IDE with PHP V5.3 support and give namespaces a whirl. As to naming conventions, it's more important to set some simple ones than to agonize over coming up with the perfect strategy. Personally, with a long background in Java development, I like to follow the Java naming conventions. I use camel-cased names for my PHP namespaces and stay away from the underscores. By using namespaces in your next PHP project, your code will be cleaner and more organized. You will become acquainted with a facility that is common to most leading languages. And you will be prepared for using the wealth of frameworks already using PHP V5.3 — and namespaces in particular.
| Description | Name | Size | Download method |
|---|---|---|---|
| Sample scripts | os-php-5.3namespaces_code.zip | 6KB | HTTP |
Information about download methods
Learn
- Read the PHP Architect article
"PHP 5.3
namespaces for the rest of us" for more insight on namespaces.
- Check out Nathan A. Good's developerWorks
article "Creating better namespaces in PHP."
- Get the basics on PHP namespaces.
- Find answers to your PHP questions in the
PHP
Namespace FAQ.
- Read more about PHP Namespace Support in NetBeans V6.8.
- Get the PDT installation
notes.
-
PHP.net is the central resource for PHP developers.
-
Check out the "Recommended PHP reading list."
-
Browse all the PHP content on developerWorks.
-
Follow developerWorks on Twitter.
-
Expand your PHP skills by checking out IBM developerWorks' PHP project resources.
-
To listen to interesting interviews and discussions for software developers, check out developerWorks podcasts.
-
Using a database with PHP? Check out the Zend Core for
IBM, a seamless, out-of-the-box, easy-to-install PHP development and production environment that supports IBM DB2 V9.
-
Stay current with developerWorks' Technical events and webcasts.
-
Check out upcoming conferences, trade shows, webcasts, and other Events around the world that are of interest to IBM open source developers.
-
Visit the developerWorks Open source zone for extensive how-to information, tools, and project updates to help you develop with open source technologies and use them with IBM's products, as well as our most popular articles and tutorials.
-
Watch and learn about IBM and open source technologies and product functions with the no-cost developerWorks On demand demos.
Get products and technologies
- Download Eclipse PDT
V2.1.
-
Innovate your next open source development project with IBM trial software, available for download or on DVD.
- Download
IBM product evaluation versions
or explore
the online trials in the IBM SOA Sandbox and get your hands on application development tools and middleware products from
DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.
Discuss
- Connect with other PHP developers by
joining the PHP Developers group in the developerWorks Community.
-
Get involved in the developerWorks community.
Connect with other developerWorks users while exploring the developer-driven blogs, forums, groups, and wikis.
-
Participate in developerWorks blogs and get involved in the developerWorks community.
-
Participate in the developerWorks PHP Forum: Developing PHP applications with IBM Information Management products (DB2, IDS).

Don Denoncourt is a free-lance consultant, trainer, mentor, and author specializing in Java technology, Groovy, Grails, and PHP. You can reach him at dondenoncourt@gmail.com.




