Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
October 1, 2012 09:00 pm GMT

Namespacing in PHP

It’s been a bumpy ride, in regards to namespace support in PHP. Thankfully, it was added to the language in PHP 5.3, and the applicable structure of PHP code has improved greatly since then. But how exactly do we use them?


What’s a Namespace?

"Don’t forget to escape the backslash when you store a namespace name in a string!"

Imagine a namespace as a drawer in which you can put all kinds of things: a pencil, a ruler, a piece of paper and so forth. These are your belongings. Directly underneath your drawer is someone else’s, and he puts the same things in it. To avoid using each other’s items, you decide to label the drawers so it’s clear what belongs to whom.

Previously, developers had to use underscores in their classes, functions and constants to separate code bases. That’s equivalent to labeling each others belongings and putting them in one big drawer. Sure, it’s at least some kind of organization, but it’s very inefficient.

Namespacing to the rescue! You can declare the same function, class, interface and constant definitions in separate namespaces without receiving fatal errors. Essentialy, a namespace is nothing more than a hierarchically labeled code block holding regular PHP code.

You are Using Them!

It is important to keep in mind that you indirectly make use of namespaces; as of PHP 5.3, all the definitions which are not yet declared in a user defined namespace fall under the global namespace.

The global namespace also holds all internal PHP definitions, like echo(), mysqli_connect(), and the Exception class. Because the global namespace has no unique identifying name, its most often referred to as the global space.

Note that it’s not an obligation to use namespacing.

Your PHP script will work perfectly fine without them, and this behavior isn’t about to change very soon.


Defining a Namespace

A namespace definition is the first statement the PHP interpreter should encounter in a PHP file. The only statement allowed to occur above a namespace declaration is a declare statement, and then again, only if it declares the encoding of the script.

Declaring a namespace is as simple as using the namespace keyword. A namespace name should obey the same rules as other identifiers in PHP. Therefore, a namespace must start with a letter or underscore, followed by any number of letters, numbers, or underscores.

<?phpnamespace MyProject {    // Regular PHP code goes here, anything goes!    function run()    {        echo 'Running from a namespace!';    }}

If you want to assign a code block to the global space, you use the namespace keyword without appending a name.

<?phpnamespace {    // Global space!}

You are allowed to have multiple namespaces in the same file.

<?phpnamespace MyProject {}namespace MySecondProject {}namespace {}

You can also scatter the same namespace throughout different files; the process of file inclusion automatically merges them. Therefore, it’s a good coding practice to limit the amount of namespace definitions to one per file, just like you would do with classes.

Namespacing is used to avoid conflicting definitions and introduce more flexibility and organization in your code base.

Note that the brackets surrounding the namespace code block are completely optional. In fact, sticking to the one-namespace-per-file rule and omitting the curly brackets makes your code a lot cleaner–there’s no need to indent the nested code.

Sub-namespaces

Namespaces can follow a certain hierarchy, much like the directories in the file system on your computer. Sub-namespaces are extremely useful for organizing the structure of a project. For example, if your project requires database access, you might want to put all the database-related code, such as a database exception and connection handler, in a sub-namespace called Database.

To maintain flexibility, it is wise to store sub-namespaces in sub-directories. This encourages structuring of your project and makes it much easier to use autoloaders that follow the PSR-0 standard.

PHP uses the backslash as its namespace separator.


Fun fact: in the RFC to decide which namespace separator should be used, they even considered using a smiley.
// myproject/database/connection.php<?phpnamespace MyProject\Databaseclass Connection {    // Handling database connections}

You can have as many sub-namespaces as you want.

<?phpnamespace MyProject\Blog\Auth\Handler\Social;class Twitter {    // Handles Twitter authentification}

Defining sub-namespaces with nested code blocks is not supported. The following example will throw a very descriptive fatal error: “Namespace declarations cannot be nested”.

<?phpnamespace MyProject {    namespace Database {        class Connection { }    }}

Calling Code from a Namespace

If you want to instantiate a new object, call a function or use a constant from a different namespace, you use the backslash notation. They can be resolved from three different view points:

Unqualified Name

This is the name of a class, function or constant without including a reference to any namespace whatsoever. If you are new to namespacing, this is the view point you are used to working from.

<?phpnamespace MyProject;class MyClass {    static function static_method()    {        echo 'Hello, world!';    }}// Unqualified name, resolves to the namespace you are currently in (MyProject\MyClass)MyClass:static_method();

Qualified Name

This is how we access the sub-namespace hierarchy; it makes use of the backslash notation.

<?phpnamespace MyProject;require 'myproject/database/connection.php';// Qualified name, instantiating a class from a sub-namespace of MyProject$connection = new Database\Connection();

The example below throws a fatal error: “Fatal error: Class ‘MyProject\Database\MyProject\FileAccess\Input’ not found” because MyProject\FileAccess\Input is approached relatively to the namespace you are currently in.

<?phpnamespace MyProject\Database;require 'myproject/fileaccess/input.php';// Trying to access the MyProject\FileAccess\Input class$input = new MyProject\FileAccess\Input();

Fully Qualified Name

The unqualified and qualified names are both relative to the namespace you are currently in. They can only be used to access definitions on that level or to dive deeper into the namespace hierarchy.

If you want to access a function, class or constant residing at a higher level in the hierarchy, then you need to use the fully qualified name–an absolute path rather than relative. This boils down to prepending your call with a backslash. This lets PHP know that this call should be resolved from the global space instead of approaching it relatively.

<?phpnamespace MyProject\Database;require 'myproject/fileaccess/input.php';// Trying to access the MyProject\FileAccess\Input class// This time it will work because we use the fully qualified name, note the leading backslash$input = new \MyProject\FileAccess\Input();

It’s not required to use the fully qualified name of internal PHP functions. Calling an unqualified name for a constant or function which does not exist in the namespace you are currently working in results in PHP searching the global namespace for them. This is a built-in fallback which does not apply to unqualified class names.

With this in mind, we can now overload internal PHP functions whilst still being able to call the original function (or constant for that matter).

<?phpnamespace MyProject;var_dump($query); // Overloaded\var_dump($query); // Internal// We want to access the global Exception class// The following will not work because there's no class called Exception in the MyProject\Database namespace and unqualified class names do not have a fallback to global space// throw new Exception('Query failed!');// Instead, we use a single backslash to indicate we want to resolve from global spacethrow new \Exception('ailed!');function var_dump() {    echo 'Overloaded global var_dump()!<br />';}

Dynamic calls

PHP is a dynamic programming language; so you can also apply this functionality for calling namespaced code. This is essentially the same as instantiating variable classes or including variable files. The namespace separator PHP uses is also a meta character in strings. Don’t forget to escape the backslash when you store a namespace name in a string!

<?phpnamespace OtherProject;$project_name = 'MyProject';$package_name = 'Database';$class_name = 'Connection';// Include a variable filerequire strtolower($project_name . '/'. $package_name .  '/' . $class_name) . '.php';// Name of a variable class in a variable namespace. Note how the backslash is escaped to use it properly$fully_qualified_name = $project_name . '\\' . $package_name . '\\' . $class_name;$connection = new $fully_qualified_name();

The namespace Keyword

Not only is the namespace keyword used to define a namespace, it can also be used to explicitly resolve to the current namespace, functionally similar to the self keyword for classes.

<?phpnamespace MyProject;function run(){    echo 'Running from a namespace!';}// Resolves to MyProject\runrun();// Explicitly resolves to MyProject\runnamespace\run();

The __NAMESPACE__ constant

Much like the self keyword cannot be used to determine what the current class name is, the namespace keyword cannot be used to determine what the current namespace is. This is why we have the __NAMESPACE__ constant.

<?phpnamespace MyProject\Database;// 'MyProject\Database'echo __NAMESPACE__;

This constant is very useful for learning if you are just starting out with namespaces; it is also helpful for debugging. As it is a string, it can also be used in combination with dynamic code calls which we previously discussed.


Aliasing or Importing

"it’s not an obligation to use namespacing"

Namespacing in PHP has support for importing. Importing is also referred to as aliasing. Only classes, interfaces, and namespaces can be aliased or imported.

Importing is a very useful and fundamental aspect of namespacing. It gives you the ability to make use of external code packages, like libraries, without having to worry about conflicting names. Importing is achieved by using the use keyword. Optionally, you can specify a custom alias with the as keyword.

use [name of class, interface or namespace] as [optional_custom_alias]

How it’s Done

A fully qualified name can be aliased to a shorter unqualified name so that you don’t have to write its fully qualified name each time you want to make use of it. Aliasing or importing should occur in the highest scope of a namespace or in the global scope. Trying to do this in the scope of a method or function is invalid syntax.

<?phpnamespace OtherProject;// This holds the MyProject\Database namespace with a Connection class in itrequire 'myproject/database/connection.php';// If we want to access the database connection of MyProject, we need to use its fully qualified name as we're in a different name space$connection = new \MyProject\Database\Connection();// Import the Connection class (it works exactly the same with interfaces)use MyProject\Database\Connection;// Now this works too! Before the Connection class was aliased PHP would not have found an OtherProject\Connection class$connection = new Connection();// Import the MyProject\Database namespaceuse MyProject\Database;$connection = new Database\Connection()

Alternatively, you can alias to it a different name:

<?phpnamespace OtherProject;require 'myproject/database/connection.php';use MyProject\Database\Connection as MyConnection;$connection = new MyConnection();use MyProject\Database as MyDatabase;$connection = new MyDatabase\Connection();

You are also allowed to import global classes, like the Exception class. When imported, you don’t have to write its fully qualified name anymore.

Note that import names are not resolved as relative to the current namespace but from an absolute standpoint, starting at the global space. This means that a leading backslash is unnecessary and not recommended.

<?phpnamespace MyProject;// Fatal error: Class 'SomeProject\Exception' not foundthrow new Exception('An exception!');// OK!throw new \Exception('An exception!');// Import global Exception. 'Exception' is resolved from an absolute standpoint, the leading backslash is unnecessaryuse Exception;// OK!throw new Exception('An exception!');

Though it is possible to dynamically call namespaced code, dynamic importing is not supported.

<?phpnamespace OtherProject;$parser = 'markdown';// This is valid PHPrequire 'myproject/blog/parser/' . $parser . '.php';// This is notuse MyProject\Blog\Parser\$parser;

Conclusion

Namespacing is used to avoid conflicting definitions and introduce more flexibility and organization in your code base. Remember that you are not obligated to use namespacing; it’s a feature used in combination with an object oriented workflow. Hopefully, however, you will consider taking your (future) PHP project to the next level by making use of namespacing. Have you decided yet?



Original Link: http://feedproxy.google.com/~r/nettuts/~3/t-5BZtKPaP0/

Share this article:    Share on Facebook
View Full Article

TutsPlus - Code

Tuts+ is a site aimed at web developers and designers offering tutorials and articles on technologies, skills and techniques to improve how you design and build websites.

More About this Source Visit TutsPlus - Code