How to use namespaces in PHP, Part 2: importing, aliases and parsing rules

Original author: Craig Buckler
  • Transfer
image
In Part 1 , we discussed why namespaces are needed in PHP, and what the reserved name namespace stands for. In this article, we explore the use statement and the way PHP resolves namespace names.

For the purposes of this article, we will use two almost identical codes, the only difference of which is in their namespaces:

lib1.php:

<?php// application library 1namespaceApp\Lib1;
const MYCONST = 'App\Lib1\MYCONST';
functionMyFunction(){
	return__FUNCTION__;
}
classMyClass{
	staticfunctionWhoAmI(){
		return__METHOD__;
	}
}
?>

lib2.php:

<?php// application library 2namespaceApp\Lib2;
const MYCONST = 'App\Lib2\MYCONST';
functionMyFunction(){
	return__FUNCTION__;
}
classMyClass{
	staticfunctionWhoAmI(){
		return__METHOD__;
	}
}
?>

Before we get started, let's recall a few definitions from PHP terminology:

Fully-qualified name

Any PHP code can refer to a fully qualified name - an identifier starting with a namespace delimiter (i.e. backslash), for example: \ App \ Lib1 \ MYCONST, \ App \ Lib2 \ MyFunction (), etc.

There are no ambiguities in full qualified names. The initial backslash acts in the same way as the file path, denoting the “root” of global space. If we were to execute various MyFunction () in our global space, they could be called from lib1.php or lib2.php using \ MyFunction ().

Full qualified names are useful for one-time function calls or object initialization. However, when you make many challenges, they become impractical. As we learn below, PHP offers other options in these cases.

Qualified Name

An identifier that has at least one namespace separator (in fact, a backslash), for example, Lib1 \ MyFunction ().

Unqualified name

An identifier without a namespace delimiter, for example MyFunction ().

Work with the same namespace


We discuss the following code:

myapp1.php:

<?phpnamespaceApp\Lib1;
require_once('lib1.php');
require_once('lib2.php');
header('Content-type: text/plain');
echo MYCONST . "\n";
echo MyFunction() . "\n";
echo MyClass::WhoAmI() . "\n";
?>

Although we have attached both lib1.php and lib2.php, the identifiers MYCONST, MyFunction, and MyClass will only refer to lib1.php. This will happen because the code myapp1.php is located in the same namespace as App \ Lib1:

result:

App\Lib1\MYCONST
App\Lib1\MyFunction
App\Lib1\MyClass::WhoAmI

Importing Namespaces (Namespace Importing)


Namespaces can be imported using the use statement, for example:

myapp2.php:

<?phpuseApp\Lib2;
require_once('lib1.php');
require_once('lib2.php');
header('Content-type: text/plain');
echo Lib2\MYCONST . "\n";
echo Lib2\MyFunction() . "\n";
echo Lib2\MyClass::WhoAmI() . "\n";
?>

You can import using one or more namespaces, separating them with a comma. In this example, we imported the App \ Lib2 namespace. We still cannot directly refer to MYCONST, MyFunction or MyClass because our code is in the global space and PHP will look for them there. But if we add the prefix “Lib2 \”, they will become qualified names, and PHP will look for them in the imported namespaces until it finds a complete match.

result:

App\Lib2\MYCONST
App\Lib2\MyFunction
App\Lib2\MyClass::WhoAmI

Namespace Aliases


Namespace aliases are arguably the most useful construct. Aliases allow you to reference long namespaces using a short name.

myapp3.php:

<?phpuseApp\Lib1asL;
useApp\Lib2\MyClassasObj;
header('Content-type: text/plain');
require_once('lib1.php');
require_once('lib2.php');
echo L\MYCONST . "\n";
echo L\MyFunction() . "\n";
echo L\MyClass::WhoAmI() . "\n";
echo Obj::WhoAmI() . "\n";
?>

The first use statement defines App \ Lib1 as "L". Any qualified name using "L" will be converted at compile time to "App \ Lib1". Therefore, we would rather refer to L \ MYCONST or L \ MyFunction than to the fully qualified name.

The second use statement is more interesting. It defines Obj as an alias for the MyClass class within the App \ Lib2 \ namespace. This operation applies only to classes - not to constants or functions. Now we can use new Obj (), or call static methods, as shown above.

result:

App\Lib1\MYCONST
App\Lib1\MyFunction
App\Lib1\MyClass::WhoAmI
App\Lib2\MyClass::WhoAmI

Parsing Rules


PHP identifier names are resolved by the following namespace rules. for more information, refer to the PHP manual ( in English / Russian )
  1. Calling qualified functions is allowed during compilation.
  2. All qualified names are translated at compile time according to the current imported namespaces. For example, if the namespace A :: B :: C is imported, a call to C :: D :: e () will be translated as A :: B :: C :: D :: e ().
  3. Inside the namespace, all qualified names are translated according to import rules, for example, if the namespace A \ B \ C is imported as C, the call C \ D \ e () is translated into A \ B \ C \ D \ e ().
  4. Unqualified class names are translated at compile time according to the current imported namespaces and full names replace short imported names, for example, if a class C in the A \ B namespace is imported as X, new X () will be translated to new A \ B \ C ().
  5. Inside the namespace, calls to unskilled functions are interpreted at compile time. For example, if MyFunction () is called within the A \ B namespace, PHP first searches for the function \ A \ B \ MyFunction (). If it is not found, PHP will look for \ MyFunction () in the global space.
  6. Calls to unskilled or qualified class names are interpreted at compile time. For example, if we call new C () within the namespace A \ B, PHP will look for the class A \ B \ C. If it is not found, this will lead to an attempt to autoload A \ B \ C.

In the next part: keywords and startup.

Read also:


How to use namespaces in PHP, Part 1: Basics
How to use namespaces in PHP, Part 3: Keywords and startup

Notes:



A / Remarks, corrections, indications of inaccuracies, etc. - welcome !

B / Code highlighted with Source Code Highlighter .

Also popular now: