From aa60b27c863f80f8089bdf6925dd178958ffe0dc Mon Sep 17 00:00:00 2001 From: Greg Beaver Date: Tue, 25 Nov 2008 04:18:33 +0000 Subject: [PATCH] document new namespace syntax, complete rewrite of docs for namespaces for 5.3 alpha3 pending release git-svn-id: https://svn.php.net/repository/phpdoc/en/trunk@269656 c90b9560-bf6c-de11-be94-00142212c4b1 --- language/namespaces.xml | 1525 +++++++++++++++++++++++++++++++++------ 1 file changed, 1290 insertions(+), 235 deletions(-) diff --git a/language/namespaces.xml b/language/namespaces.xml index ab204a54b8..bd8e9a000e 100644 --- a/language/namespaces.xml +++ b/language/namespaces.xml @@ -1,5 +1,5 @@ - + Namespaces @@ -7,208 +7,683 @@ Namespaces overview - Namespaces in PHP are designed to solve scoping problem in large PHP - libraries. In PHP, all class definitions are global. Thus, when a library - author creates various utility or public API classes for the library, he must - be aware of the possibility that other libraries with similar functionality - would exist and thus choose unique names so that these libraries could be - used together. Usually it is solved by prefixing the class names with an - unique string - e.g., database classes would have prefix - My_Library_DB, etc. As the library grows, prefixes add up, - leading to the very long names. + What are namespaces? In the broadest definition namespaces are a way of encapsulating + items. This can be seen as an abstract concept in many places. For example, in any + operating system directories serve to group related files, and act as a namespace for + the files within them. As a concrete example, the file foo.txt can + exist in both directory /home/greg and in /home/other, + but two copies of foo.txt cannot co-exist in the same directory. In + addition, to access the foo.txt file outside of the + /home/greg directory, we must prepend the directory name to the file + name using the directory separator to get /home/greg/foo.txt. This + same principle extends to namespaces in the programming world. - The namespaces allow the developer to manage naming scopes without using the - long names each time the class is referred to, and solve the problem of - shared globals space without making code unreadable. + In the PHP world, namespaces are designed to solve two problems that authors + of libraries and applications encounter when creating re-usable code elements + such as classes or functions: + + + + + Name collisions between code you create, and + internal PHP classes/functions/constants or third-party classes/functions/constants. + + + + + Ability to alias (or shorten) Extra_Long_Names designed to alleviate the first problem, + improving readability of source code. + + + + - Namespaces are available in PHP as of PHP 5.3.0. This section is experimental - and subject to changes. + PHP Namespaces provide a way in which to group related classes, + functions and constants. Here is an example of namespace syntax in PHP: + + + + ]]> + + + Namespaces are available in PHP as of PHP 5.3.0. - Namespace definition + Defining namespaces - The namespace is declared using namespace - keyword, which should be at the very beginning of the file. Example: + Although any valid PHP code can be contained within a namespace, only three + type of code are affected by namespaces: classes, functions and constants. + + + Namespaces are declared using the namespace + keyword. A file containing a namespace must declare the namespace + at the top of the file before any other code. - Defining namespace + Declaring a single namespace ]]> - Same namespace name can be used in multiple files. + The only code construct allowed before a namespace declaration is the + declare statement, for defining encoding of a source file. In addition, + no non-PHP code may precede a namespace declaration, including extra whitespace: + + Declaring a single namespace + + + +]]> + + - - Namespace can contain class, constant and function definitions, but no free code. + In addition, unlike any other PHP construct, the same namespace may be defined + in multiple files, allowing splitting up of a namespace's contents across the filesystem. + + + Declaring sub-namespaces + + Much like directories and files, PHP namespaces also contain the ability to specify + a hierarchy of namespace names. Thus, a namespace name can be defined with + sub-levels: + + Declaring a single namespace with hierarchy + + +]]> + + + The above example creates constant MyProject\Sub\Level\CONNECT_OK, + class MyProject\Sub\Level\Connection and function + MyProject\Sub\Level\Connection. + + + + Defining multiple namespaces in the same file - Namespace definition does the following: - + Multiple namespaces may also be declared in the same file. There are two allowed + syntaxes. + + + + Declaring multiple namespaces, simple combination syntax + + +]]> + + + + + This syntax is not recommended for combining namespaces into a single file. + Instead it is recommended to use the alternate bracketed syntax. + + + + Declaring multiple namespaces, bracketed syntax + + +]]> + + + + + It is strongly discouraged as a coding practice to combine multiple namespaces into + the same file. The primary use case is to combine multiple PHP scripts into the same + file. + + + To combine global non-namespaced code with namespaced code, only bracketed syntax is + supported. Global code should be + encased in a namespace statement with no namespace name as in: + + Declaring multiple namespaces and unnamespaced code + + +]]> + + + + + No PHP code may exist outside of the namespace brackets except for an opening + declare statement. + + Declaring multiple namespaces and unnamespaced code + + +]]> + + + + + + Using namespaces: Basics + + Before discussing the use of namespaces, it is important to understand how PHP + knows which namespaced element your code is requesting. A simple analogy can be made + between PHP namespaces and a filesystem. There are three ways to access a file in a + file system: + - Inside namespace, all class, function and constant names in definitions are - automatically prefixed with namespace name. The class name is always the - full name, i.e. in the example above the class is called - MyProject::DB::Connection. + Relative file name like foo.txt. This resolves to + currentdirectory/foo.txt where currentdirectory is the + directory currently occupied. So if the current directory is + /home/foo, the name resolves to /home/foo/foo.txt. - - Constant definitions create constant which is composed of namespace name and constant name. - Like class constants, namespace constant can only contains static values. - + + Relative path name like subdirectory/foo.txt. This resolves + to currentdirectory/subdirectory/foo.txt. + - - Unqualified class name (i.e., name not containing ::) - is resolved at runtime following this procedure: - - - - Class is looked up inside the current namespace (i.e. prefixing the - name with the current namespace name) without attempting to - autoload. - - - - - Class is looked up inside the global namespace without attempting to - autoload. - - - - - Autoloading for name in current namespace is attempted. - - - - If previous failed, lookup fails. - - - + + Absolute path name like /main/foo.txt. This resolves + to /main/foo.txt. + + + + The same principle can be applied to namespaced elements in PHP. For + example, a class name can be referred to in three ways: + + + + Unqualified name, or an unprefixed class name like + $a = new foo(); or + foo::staticmethod();. If the current namespace is + currentnamespace, this resolves to + currentnamespace\foo. If + the code is global, non-namespaced code, this resolves to foo. + + + One caveat: unqualified names for functions and constants will + resolve to global functions and constants if the namespaced function or constant + is not defined. See Using namespaces: + fallback to global function/constant for details. + - - Unqualified function name (i.e., name not containing - ::) is looked up at runtime first in the current namespace - and then in the global space. - + + Qualified name, or a prefixed class name like + $a = new subnamespace\foo(); or + subnamespace\foo::staticmethod();. If the current namespace is + currentnamespace, this resolves to + currentnamespace\subnamespace\foo. If + the code is global, non-namespaced code, this resolves to subnamespace\foo. + - - Unqualified constant names are looked up first at current namespace and then - among globally defined constants. - + + Fully qualified name, or a prefixed name with global prefix operator like + $a = new \currentnamespace\foo(); or + \currentnamespace\foo::staticmethod();. This always resolves + to the literal name specified in the code, currentnamespace\foo. + - - See also the full name resolution rules. + - - - - - Using namespaces - Every class and function in a namespace can be referred to by the full name - - e.g. MyProject::DB::Connection or - MyProject::DB::connect - at any time. - - Using namespaced name - - -]]> - - - - - - Namespaces can be imported into current context (global or namespace) using - the use operator. The syntax for the operator is: + Here is an example of the three kinds of syntax in actual code: + file1.php -]]> + ]]> + + file2.php + + + ]]> - The imported name works as follows: every time that the compiler encounters - the local name Othername (as stand-alone name or as - prefix to the longer name separated by ::) the imported - name Some::Name is substituted instead. - - - use can be used only in global scope, not inside - function or class. Imported names have effect from the point of import to - the end of the current file. It is recommended to put imports at the - beginning of the file to avoid confusion. - - + Note that to access any global + class, function or constant, a fully qualified name can be used, such as + \strlen or \Exception or + \INI_ALL. - Importing and accessing namespace + Accessing global classes, functions and constants from within a namespace + ]]> + + + + + + Namespaces and dynamic language features + + PHP's implementation of namespaces is influenced by its dynamic nature as a programming + language. Thus, to convert code like the following example into namespaced code: + + Dynamically accessing elements + example1.php: + + + ]]> + + + One must use the fully qualified name (class name with namespace prefix). + Note that because there is no difference between a qualified and a fully qualified Name + inside a dynamic class name, function name, or constant name, the leading backslash is + not necessary. + + Dynamically accessing namespaced elements + + + ]]> + + + + + Be sure to read the note about + escaping namespace names in strings. + + + + namespace keyword and __NAMESPACE__ constant + + PHP supports two ways of abstractly accessing elements within the current namespace, + the __NAMESPACE__ magic constant, and the namespace + keyword. + + + The value of __NAMESPACE__ is a string that contains the current + namespace name. In global, un-namespaced code, it contains an empty string. + + __NAMESPACE__ example, namespaced code + + +]]> + + + + __NAMESPACE__ example, global code + + +]]> + + + The __NAMESPACE__ constant is useful for dynamically constructing + names, for instance: + + using __NAMESPACE__ for dynamic name construction + + ]]> - - - The import operation is compile-time only, all local names are converted to - their full equivalents by the compiler. Note that it won't translate names - in strings, so callbacks can't rely on import rules. - - + The namespace keyword can be used to explicitly request + an element from the current namespace or a sub-namespace. It is the namespace + equivalent of the self operator for classes. + + the namespace operator, inside a namespace + + +]]> + + + + the namespace operator, in global code + + +]]> + + + + Using namespaces: Aliasing/Importing + + The ability to refer to an external fully qualified name with an alias, or importing, + is an important feature of namespaces. This is similar to the + ability of unix-based filesystems to create symbolic links to a file or to a directory. + + + PHP namespaces support + two kinds of aliasing or importing: aliasing a class name, and aliasing a namespace name. + Note that importing a function or constant is not supported. + + + In PHP, aliasing is accomplished with the use operator. Here + is an example showing all 3 kinds of importing: + + importing/aliasing with the use operator + + +]]> + + + Note that for namespaced names (fully qualified namespace names containing + namespace separator, such as Foo\Bar as opposed to global names that + do not, such as FooBar), the leading backslash is unnecessary and not + allowed, as import names + must be fully qualified, and are not processed relative to the current namespace. + + + PHP additionally supports a convenience shortcut to place multiple use statements + on the same line + + importing/aliasing with the use operator, multiple use statements combined + + +]]> + + + + + Importing is performed at compile-time, and so does not affect dynamic class, function + or constant names. + + Importing and dynamic names + + +]]> + + + + + In addition, importing only affects unqualified and qualified names. Fully qualified + names are absolute, and unaffected by imports. + + Importing and fully qualified names + + +]]> + + + + Global space Without any namespace definition, all class and function definitions are placed into the global space - as it was in PHP before namespaces were - supported. Prefixing a name with :: will specify that + supported. Prefixing a name with \ will specify that the name is required from the global space even in the context of the namespace. @@ -216,42 +691,71 @@ use Foo::Bar as Bar; -]]> + ]]> - - - __NAMESPACE__ + + Using namespaces: fallback to global function/constant - The compile-time constant __NAMESPACE__ is defined to - the name of the current namespace. Outside namespace this constant has the - value of empty string. This constant is useful when one needs to compose - full name for local namespaced names. + Inside a namespace, when PHP encounters a unqualified Name in a class name, function or + constant context, it resolves these with different priorities. Class names always + resolve to the current namespace name. Thus to access internal or non-namespaced + user classes, One must refer to them with their fully qualified Name as in: - Using __NAMESPACE__ + Accessing global classes inside a namespace + ]]> + + + + + For functions and constants, PHP will fall back to global functions or constants + if a namespaced function or constant does not exist. + + global functions/constants fallback inside a namespace + + -]]> + ]]> @@ -259,112 +763,133 @@ set_error_handler(__NAMESPACE__ . "::foo"); Name resolution rules + + For the purposes of these resolution rules, here are some important definitions: + + Namespace name definitions + + Unqualified name + + + This is an identifier without a namespace separator, such as Foo + + + + + Qualified name + + + This is an identifier with a namespace separator, such as Foo\Bar + + + + + Fully qualified name + + + This is an identifier with a namespace separator that begins with a namespace + separator, such as \Foo\Bar. namespace\Foo + is also a fully qualified name. + + + + + Names are resolved following these resolution rules: - All qualified names are translated during compilation according to current - import rules. In example, if the namespace A::B::C is imported, a call to - C::D::e() is translated to A::B::C::D::e(). + Calls to fully qualified functions, classes or constants are resolved at compile-time. + For instance new \A\B resolves to class A\B. + + + + + All unquaified and qualified names (not fully qualified names) are translated during + compilation according to current + import rules. For example, if the namespace A\B\C is imported as + C, a call to + C\D\e() is translated to A\B\C\D\e(). + + + + + Inside a namespace, all qualified names not translated according to import + rules have the current namespace prepended. For example, if a call + to C\D\e() is performed within namespace A\B, + it is translated to A\B\C\D\e(). Unqualified class names are translated during compilation according to current import rules (full name substituted for short imported name). In example, if - the namespace A::B::C is imported, new C() is - translated to new A::B::C(). + the namespace A\B\C is imported as C, new C() is + translated to new A\B\C(). - Inside namespace, calls to unqualified functions that are defined in the - current namespace (and are known at the time the call is parsed) are - interpreted as calls to these namespace functions, at compile time. - - - - - Inside namespace (say A::B), calls to unqualified functions that are not - defined in current namespace are resolved at run-time. Here is how a + Inside namespace (say A\B), calls to unqualified functions are resolved at run-time. + Here is how a call to function foo() is resolved: It looks for a function from the current namespace: - A::B::foo(). + A\B\foo(). - It tries to find and call the internal function + It tries to find and call the global function foo(). - - To call a user defined function in the global namespace, - ::foo() has to be used. - - Inside namespace (say A::B), calls to unqualified class names are - resolved at run-time. Here is how a call to - new C() is resolved: + Inside namespace (say A\B), calls to unqualified or qualified + class names (not fully qualified class names) + are resolved at run-time. Here is how a call to + new C() or new D\E() is resolved. + For new C(): It looks for a class from the current namespace: - A::B::C. + A\B\C. - It tries to find and call the internal class - C. - - - - - It attemts to autoload A::B::C. + It attemts to autoload A\B\C. - To reference a user defined class in the global namespace, - new ::C() has to be used. + For new D\E(): - - + + + + It looks for a class by prepending the current namespace: + A\B\D\E. + + + + + It attemts to autoload A\B\D\E. + + + - Calls to qualified functions are resolved at run-time. Here is how a call - to A::B::foo() is resolved: - - - - - It looks for a function foo() in the namespace - A::B. - - - - - It looks for a class A::B and call its static - method foo(). It will autoload the class if - necessary. - - - - - - - Qualified class names are resolved in compile-time as class from corresponding - namespace. For example, new A::B::C() refers to class - C from namespace A::B. + To reference any global class in the global namespace, + its fully qualified name new \C() must be used. @@ -375,43 +900,573 @@ set_error_handler(__NAMESPACE__ . "::foo"); ]]> + + FAQ: things you need to know about namespaces + + This FAQ is split into two sections: common questions, and some specifics of + implementation that are helpful to understand fully. + + + First, the common questions. + + + + If I don't use namespaces, should + I care about any of this? + + + + + How do I use internal or global + classes in a namespace? + + + + + How do I use namespaces classes + functions, or constants in their own namespace? + + + + + + How does a name like \my\name or \name + resolve? + + + + + + How does a name like + my\name resolve? + + + + + How does an unqualified class name + like name resolve? + + + + + How does an unqualified function + name or unqualified constant name + like name resolve? + + + + + + There are a few implementation details of the namespace implementations + that are helpful to understand. + + + + Import names cannot conflict with + classes defined in the same file. + + + + + Nested namespaces are not allowed. + + + + + + Neither functions nor + constants can be imported via the use + statement. + + + + + Dynamic namespace names (quoted + identifiers) should escape backslash. + + + + + Undefined Constants referenced + using any backslash die with fatal error + + + + + Cannot override special + constants NULL, TRUE, FALSE, ZEND_THREAD_SAFE or ZEND_DEBUG_BUILD + + + + + + If I don't use namespaces, should I care about any of this? + + No. Namespaces do not affect any existing code in any way, or any + as-yet-to-be-written code that does not contain namespaces. You can + write this code if you wish: + + + + Accessing global classes outside a namespace + + + + + + + This is functionally equivalent to: + + + + Accessing global classes outside a namespace + + + + + + + + How do I use internal or global classes in a namespace? + + + Accessing internal classes in namespaces + + +]]> + + + + + + + How do I use namespaces classes, functions, or constants in their own + namespace? + + + + Accessing internal classes, functions or constants in namespaces + + +]]> + + + + + + + How does a name like <literal>\my\name</literal> or <literal>\name</literal> + resolve? + + + Names that begin with a \ always resolve to what they + look like, so \my\name is in fact my\name, + and \Exception is Exception. + + Fully Qualified names + + +]]> + + + + + + How does a name like <literal>my\name</literal> resolve? + + Names that contain a backslash but do not begin with a backslash like + my\name can be resolved in 2 different ways. + + + If there is + an import statement that aliases another name to my, then + the import alias is applied to the my in my\name. + + + Otherwise, the current namespace name is prepended to my\name. + + + + Qualified names + + +]]> + + + + + + How does an unqualified class name like <literal>name</literal> resolve? + + Class names that do not contain a backslash like + name can be resolved in 2 different ways. + + + If there is + an import statement that aliases another name to name, then + the import alias is applied. + + + Otherwise, the current namespace name is prepended to name. + + + + Unqualified class names + + +]]> + + + + + + + How does an unqualified function name or unqualified constant name + like <literal>name</literal> resolve? + + + Function or constant names that do not contain a backslash like + name can be resolved in 2 different ways. + + + First, the current namespace name is prepended to name. + + + Finally, if the constant or function name does not exist + in the current namespace, a global constant or function name + is used if it exists. + + + + Unqualified function or constant names + + +]]> + + + + + + Import names cannot conflict with classes defined in the same file. + + The following script combinations are legal: + + file1.php + + + ]]> + + another.php + + + ]]> + + file2.php + + + ]]> + + + + + There is no name conflict, even though the class MyClass exists + within the my\stuff namespace, because the MyClass definition is + in a separate file. However, the next example causes a fatal error on name conflict + because MyClass is defined in the same file as the use statement. + + + + ]]> + + + + + + Nested namespaces are not allowed. + + PHP does not allow nesting namespaces + + + + ]]> + + + However, it is easy to simulate nested namespaces like so: + + + + ]]> + + + + + + Neither functions nor constants can be imported via the <literal>use</literal> + statement. + + The only elements that are affected by use statements are namespaces + and class names. In order to shorten a long constant or function, import its containing + namespace + + + + ]]> + + + + + + Dynamic namespace names (quoted identifiers) should escape backslash + + It is very important to realize that because the backslash is used as an escape character + within strings, it should always be doubled when used inside a string. Otherwise + there is a risk of unintended consequences: + + Dangers of using namespaced names inside a double-quoted string + + + ]]> + + + Inside a single-quoted string, the backslash escape sequence is much safer to use, but it + is still recommended practice to escape backslashes in all strings as a best practice. + + + + Undefined Constants referenced using any backslash die with fatal error + + Any undefined constant that is unqualified like FOO will + produce a notice explaining that PHP assumed FOO was the value + of the constant. Any constant, qualified or fully qualified, that contains a + backslash will produce a fatal error if not found. + + Undefined constants + + + ]]> + + + + + + Cannot override special constants NULL, TRUE, FALSE, ZEND_THREAD_SAFE or ZEND_DEBUG_BUILD + + Any attempt to define a namespaced constant that is a special, built-in constant + results in a fatal error + + Undefined constants + + + ]]> + + + + +