Core PHP 5 programs with output 15 Q/A 5 MCQs

Learning Objectives – after this chapter you will be able to:

  • Explain the two problems namespaces solve: name collisions and very long names.
  • Declare namespaces and sub-namespaces, including several in one file.
  • Refer to names using unqualified, qualified and fully qualified forms.
  • Import and alias classes, functions and constants with use.
  • Use the global space, the namespace operator and the __NAMESPACE__ constant.
What is a Namespace?

In the broadest sense, namespaces are a way of encapsulating items. You meet this idea in many places. In any operating system, directories group related files and act as a namespace for the files within them: the file foo.txt can exist in both /home/greg and /home/other, but two copies of foo.txt cannot exist in the same directory. To access foo.txt from outside /home/greg, we prepend the directory name with the directory separator: /home/greg/foo.txt. The same principle extends to namespaces in programming.

In PHP, namespaces solve two problems that authors of libraries and applications meet when they create reusable classes and functions:

  1. Name collisions between your code and internal PHP classes, functions and constants, or third-party code.
  2. The need to write Extra_Long_Names (invented to avoid the first problem) – namespaces let you alias (shorten) them, improving readability.

PHP namespaces group related classes, interfaces, functions and constants. Here is the general syntax:

<?php
namespace my\name;

class MyClass {}
function myfunction() {}
const MYCONST = 1;

$a = new MyClass;                // my\name\MyClass
$c = new \my\name\MyClass;       // fully qualified name
$a = strlen('hi');               // falls back to the global strlen()
$d = namespace\MYCONST;          // the namespace operator
$d = __NAMESPACE__ . '\MYCONST';
echo constant($d);
Why Do We Need Namespaces?

As your PHP code library grows, there is an increasing risk of accidentally re-defining a function or class name that has been declared before. The problem gets worse when you add third-party components or plug-ins: what if two or more of them implement a Database or User class? Namespaces solve such name collisions. All modern PHP frameworks (Laravel, Symfony) and Composer packages rely on them.

Defining Namespaces

By default, all constant, class and function names are placed in the global space – as they were before PHP supported namespaces (PHP 5.3).

Namespaces are declared with the namespace keyword. A file containing a namespace must declare it at the top of the file before any other code – with one exception: the declare keyword. No non-PHP code, not even white space or HTML, may precede the declaration:

<html>
<?php
namespace MyProject;   // fatal error – namespace must be the first statement in the script

Unlike any other PHP construct, the same namespace may be defined in several files, splitting its contents across the file system.

Declaring a single namespace
File: htdocs/phpbook/ch16/lib1.php
<?php
namespace MyProject;

const CONNECT_OK = 1;
class Connection
{
    public function info() { return "Connection class in " . __NAMESPACE__; }
}
function connect() { return "MyProject\\connect() called"; }
Declaring sub-namespaces

Like directories and files, namespaces can have a hierarchy:

File: htdocs/phpbook/ch16/lib2.php
<?php
namespace MyProject\Sub\Level;

const CONNECT_OK = 2;
class Connection
{
    public function info() { return "Connection class in " . __NAMESPACE__; }
}
function connect() { return __FUNCTION__ . "() called"; }

This creates the constant MyProject\Sub\Level\CONNECT_OK, the class MyProject\Sub\Level\Connection and the function MyProject\Sub\Level\connect. Both files define a class named Connection – and there is no collision:

File: htdocs/phpbook/ch16/usens.php
<?php
require "lib1.php";
require "lib2.php";

$a = new MyProject\Connection();
$b = new MyProject\Sub\Level\Connection();
echo $a->info() . "<br>";
echo $b->info() . "<br>";
echo MyProject\connect() . "<br>";
echo MyProject\Sub\Level\connect() . "<br>";
echo "CONNECT_OK values: " . MyProject\CONNECT_OK . " and " . MyProject\Sub\Level\CONNECT_OK;
?>
OUTPUT browser · http://localhost/phpbook/ch16/usens.php
Connection class in MyProject
Connection class in MyProject\Sub\Level
MyProject\connect() called
MyProject\Sub\Level\connect() called
CONNECT_OK values: 1 and 2
Several Namespaces in One File

Multiple namespaces may be declared in one file, with two possible syntaxes. The simple combination syntax (one namespace X; after another) is not recommended. Use the bracketed syntax:

File: htdocs/phpbook/ch16/multins.php
<?php
namespace MyProject {
    const CONNECT_OK = 1;
    class Connection { public static function start() { return "MyProject connection started"; } }
    function connect() { return "MyProject\\connect()"; }
}

namespace AnotherProject {
    const CONNECT_OK = 1;
    class Connection { public static function start() { return "AnotherProject connection started"; } }
    function connect() { return "AnotherProject\\connect()"; }
}

namespace { // global code
    echo MyProject\connect() . "<br>";
    echo MyProject\Connection::start() . "<br>";
    echo AnotherProject\Connection::start();
}
?>
OUTPUT browser · http://localhost/phpbook/ch16/multins.php
MyProject\connect()
MyProject connection started
AnotherProject connection started

To combine global (non-namespaced) code with namespaced code, only the bracketed syntax is allowed; the global code is placed in a namespace { … } block with no name. No PHP code may exist outside the brackets except an opening declare statement.

Putting several namespaces in one file is discouraged as a coding practice. The main use is to combine several scripts into one file for deployment. Normally each class has its own file (see autoloading, Chapter 17).

Referring to Names
Kind of nameExampleResolved (inside namespace App)
UnqualifiedConnectionApp\Connection
QualifiedSub\ConnectionApp\Sub\Connection
Fully qualified\MyProject\ConnectionMyProject\Connection (leading \ = from the global root)
Importing and Aliasing with use

The ability to refer to an external fully qualified name with an alias (importing) is an important feature of namespaces – similar to creating symbolic links to files in Unix. In PHP, aliasing is done with the use operator. You can import classes, interfaces, namespaces and – since PHP 5.6 – functions (use function) and constants (use const).

File: htdocs/phpbook/ch16/alias.php
<?php
namespace Shop;

require "lib1.php";
require "lib2.php";

use MyProject\Connection as Main;            // alias a class
use MyProject\Sub\Level\Connection;           // import with its own short name
use MyProject\Sub\Level;                      // alias a namespace
use function MyProject\connect;               // import a function
use const MyProject\CONNECT_OK;               // import a constant
use ArrayObject;                              // import a global class

$x = new Main();
$y = new Connection();
echo $x->info() . "<br>";
echo $y->info() . "<br>";
echo Level\connect() . "<br>";
echo connect() . "<br>";
echo "CONNECT_OK = " . CONNECT_OK . "<br>";
$arr = new ArrayObject([1, 2, 3]);            // without "use ArrayObject" PHP would look for Shop\ArrayObject
echo "ArrayObject count: " . count($arr);
?>
OUTPUT browser · http://localhost/phpbook/ch16/alias.php
Connection class in MyProject
Connection class in MyProject\Sub\Level
MyProject\Sub\Level\connect() called
MyProject\connect() called
CONNECT_OK = 1
ArrayObject count: 3

Several imports can be combined in one statement: use My\Full\Classname as Another, My\Full\NSname;. Since PHP 7 related imports can also be grouped: use MyProject\Sub\Level\{Connection, function connect};.

Importing is performed at compile time, so it does not affect dynamic class names held in strings: with $a = 'Another'; new $a; PHP looks for the global class Another, not the alias. Dynamic names must always be fully qualified.

The Global Space

Without any namespace definition, all classes and functions are placed in the global space. Prefixing a name with \ specifies that the name is required from the global space even inside a namespace:

File: htdocs/phpbook/ch16/globalspace.php
<?php
namespace A\B\C;

/* This function is A\B\C\strlen */
function strlen($s)
{
    return "my own strlen: " . \strlen($s) . " characters";   // call the global strlen
}
echo strlen("namespace") . "<br>";       // calls A\B\C\strlen
echo \strlen("namespace") . "<br>";      // calls PHP's strlen
echo "Current namespace: " . __NAMESPACE__;
?>
OUTPUT browser · http://localhost/phpbook/ch16/globalspace.php
my own strlen: 9 characters
9
Current namespace: A\B\C

When PHP meets an unqualified function or constant name inside a namespace and no such name exists in the namespace, it falls back to the global function or constant – that is why strlen('hi') works in any namespace. For classes there is no fallback: new ArrayObject inside namespace Shop means Shop\ArrayObject unless you import it or write \ArrayObject.

The __NAMESPACE__ Constant and the namespace Operator

__NAMESPACE__ is a string that always contains the current namespace name; in the global space it is an empty string. The keyword namespace can also be used as an operator to refer explicitly to the current namespace, e.g. namespace\connect().

File: htdocs/phpbook/ch16/nsconst.php
<?php
namespace App\Lib1;

function hello() { return "Hello from " . __FUNCTION__; }
echo __NAMESPACE__ . "<br>";               // outputs: App\Lib1
echo namespace\hello() . "<br>";           // current namespace
$fn = __NAMESPACE__ . '\hello';            // dynamic name must be fully qualified
echo $fn();
?>
OUTPUT browser · http://localhost/phpbook/ch16/nsconst.php
App\Lib1
Hello from App\Lib1\hello
Hello from App\Lib1\hello
Key Takeaways
  • Namespaces group classes, interfaces, functions and constants and prevent name collisions.
  • Declare with namespace Name; as the first statement of the file; sub-namespaces use \.
  • Use bracketed syntax for several namespaces (and global code) in one file.
  • Names can be unqualified, qualified or fully qualified (\ from the root).
  • use imports and aliases (as); use function and use const import functions and constants.
  • Functions and constants fall back to the global space; classes do not.
  • __NAMESPACE__ holds the current namespace; namespace\x refers to it explicitly.
Program File

Extract the ZIP into C:\xampp\htdocs. It creates the folder phpbook/ch16 used in the file labels above; open the programs at http://localhost/phpbook/… with Apache (and MySQL, where needed) started in the XAMPP Control Panel.

Question / Answer (15 questions)

Answer : A named container that groups related classes, interfaces, functions and constants, so that the same names can be used in different namespaces without colliding – similar to directories grouping files.

Answer : Name collisions between your code, PHP's internal names and third-party code; and the need for very long names, which namespaces allow you to alias or shorten.

Answer : PHP 5.3.

Answer : It must be the first statement in the file; only a declare statement may precede it – no HTML or white space.

Answer : With backslashes in the name, e.g. namespace MyProject\Sub\Level;

Answer : Yes. Unlike other constructs, the same namespace can be declared in many files.

Answer : Use the bracketed syntax: namespace A { … } namespace B { … } and namespace { … } for the global code.

Answer : A qualified name contains a namespace separator but no leading backslash (Sub\Connection) and is resolved relative to the current namespace; a fully qualified name starts with \ (\MyProject\Connection) and is resolved from the global root.

Answer : It imports a class, interface, namespace, function (use function) or constant (use const) into the current file, optionally with an alias: use My\Full\Classname as Another;

Answer : Imports are processed at compile time, while a class name stored in a string is resolved at run time, so dynamic names must be fully qualified.

Answer : The space where all names live when no namespace is declared. Prefix a name with \ to use the global name inside a namespace, e.g. \strlen() or \ArrayObject.

Answer : For functions and constants, PHP first looks in the current namespace and then falls back to the global one; for classes there is no fallback.

Answer : A magic constant containing the name of the current namespace as a string; it is empty in the global space.

Answer : The keyword namespace used in a name to refer explicitly to the current namespace, e.g. namespace\hello() or namespace\MYCONST.

Answer : Because PHP looks for the class Shop\ArrayObject. You must write \ArrayObject or add use ArrayObject; at the top of the file.
MCQ Test : Check Your Understanding (5 questions)

Select an option and press Check Answer, or answer all questions and press Submit Test to see your score. Each answer comes with an explanation.

Q1. Which keyword declares a namespace?

Show Answer

Correct Answer : B. namespace
namespace Name; declares it.

Q2. Which separator is used in namespace names?

Show Answer

Correct Answer : C. \
PHP uses the backslash.

Q3. \strlen("x") inside a namespace calls:

Show Answer

Correct Answer : B. The global strlen
A leading backslash means the global space.

Q4. Which statement imports a function from a namespace?

Show Answer

Correct Answer : C. use function MyProject\connect;
Functions are imported with use function.

Q5. What is __NAMESPACE__ in the global space?

Show Answer

Correct Answer : C. An empty string
It contains the current namespace name, empty in the global space.

Bibliography/References

The notes on this page are the author’s own compilation from the e-book PHP: Basics to Advance. Every program was run on Apache with PHP 8 and MariaDB, and the output shown is the real result of that run. The works listed below were consulted and are cited for attribution and further reading. Product names and trademarks belong to their respective owners.

  1. The PHP Group. (n.d.). PHP Manual – Namespaces overview. https://www.php.net/manual/en/language.namespaces.rationale.php
  2. The PHP Group. (n.d.). PHP Manual – Defining multiple namespaces in the same file. https://www.php.net/manual/en/language.namespaces.definitionmultiple.php
  3. The PHP Group. (n.d.). PHP Manual – Using namespaces: Aliasing/Importing. https://www.php.net/manual/en/language.namespaces.importing.php
  4. The PHP Group. (n.d.). PHP Manual – Global space. https://www.php.net/manual/en/language.namespaces.global.php
  5. The PHP Group. (n.d.). PHP Manual – namespace keyword and __NAMESPACE__ magic constant. https://www.php.net/manual/en/language.namespaces.nsconstants.php