Like many languages, PHP does not allow you to have two classes with the same name at a global level. While on the surface this may sound like a good idea, it becomes a problem when you import libraries and a name collision occurs (completing libraries have one or more classes with the same name). To solve this issue the concept of “name spaces” was added in PHP 5.3.
A name space allows you to partition code into logical groups by defining them into their own “namespace”. A text string after the “namespace” keyword identifies the name space and all code below it then lives within that name space. Name spaces also provide a way to group interfaces functions and constants.
As you application grows name spaces become essential to logically group code and to keep code separate from other code. Another great benefit to name spaces is when generating documentation. Name spaced code gets grouped accordingly by the most common PHP Documentors like Doxygen, phpDocumentor and phpDox.
Lets look at some simple examples so the idea is easy to follow and implement.
Without using a name space a simple class looks like:
<?php /** * brief Handle all User Option preferences */ class UserOptions { public function getOptions() { …... } }
To define a name space, use the “namespace” keyword followed by a path identifier. Here I have used AppUtilities to wrap the UserOptions class:
<?php namespace AppUtilities; /** * brief Handle all User Option preferences for a normall user of the application */ class UserOptions { /** * Given a user object retrieve all associated options for the user and return them in * an array and key-value pairs. */ public function getOptions(User $user) { …... } }
The “namespace” keyword must have no other keywords before it but comments are OK and needed for most documentation generators.
Now that we have the class defined inside a Utilities name space we can access it in two ways, and here it is assumed we are not trying to access it from another name space:
$userOption = new AppUtilitiesUserOptions(); $options = $userOption->getOptions();
or
use AppUtilities; $userOption = new UserOptions(); $options = $userOption->getOptions();
If we are trying to use the class from within another name space then the “use” keyword will need to be changed to include the class name like so:
use AppUtilitiesUserOptions;
This allows the compiler to import the correct class name from the correct name space. Let see another example of this, first we define a class:
<?php namespace AppThirdPartyInvoicing; /** * brief Invoice module options for all users from ThirdParty software sales. */ Class UserOptions { public function getOptions() { …. } }
In our example, we were given a new invoicing module and it also has a UserOptions class that has no relationship to our original UserOptions class and it even has a common method name. Let use both in a sample program.
Referencing the two classes in our code we get:
<?php namespace App; Class TestExample { /** * Do a billing run * * @return void */ public function BillingRun() { …. $userOptions = new AppUtilitiesUserOptions(); $billingOptions = new AppThirdPatyInvoicingUserOptions(); ... } }
This looks messy and we can shorten it using an alias to the sub-name space as shown below:
<?php namespace App; use AppUtilities as Util; use AppThirdPatyInvoicing as Billing; Class TestExample { /** * Do a billing run * * @return void */ public function BillingRun() { …. $userOptions = new UtilUserOptions(); $billingOptions = new BillingUserOptions(); ... } }
What if you don’t use namespaces?
In a Laravel application, you can’t take advantage of custom directories if you don’t use a name space., Instead, you need to add additional paths to your composer.json file to include the paths. This can be handy on a quick and dirty small application but at some point as the application grows you need to move to name spaces. Here is an example of the “autoload” class map entry from a Laravel composer.json file, it has a Models Directory and a ConfigHelprers directory defined:
"autoload": { "classmap": [ "database", "app/Models", "app/ConfigHelpers" ], "psr-4": { "App\": "app/" } },
Getting in early and using well thought out name space keywords in your application will save time down the track when the functionality expands. In a complex Framework like Laravel, name spaces are used everywhere and each release new third party composer based packages are being made available only compounding the usage.