Lesson 30 of 100
Organization12 min5 checksPHP 8.5

Namespaces: Organize Related Classes

Learn how to declare a namespace and how PHP resolves unqualified, qualified and fully qualified class names.

01 · THE IDEAREAD → TRY → LEARN

Why namespaces exist

As a project grows, two classes will eventually want the same short name. A shop might have an Invoice for billing and another Invoice for display. A namespace gives each class a prefix, so the full names differ even when the short names match.

A useful analogy is a filesystem. A file name alone depends on the current directory, a path with folders is relative to where you are, and an absolute path starts at the root. PHP resolves class names with the same three ideas.

Declaring a namespace

The namespace keyword names the namespace for the code that follows. It must be the first statement in the file, apart from declare. Backslashes separate the levels.

Example
<?php
namespace App\Models;

class User
{
}

echo User::class, "\n";
echo \strlen('abc'), "\n";
Output
App\Models\User
3

The class is now really named App\Models\User. The ::class constant shows that full name. The leading backslash in \strlen is explained below.

Three ways to write a name

Inside the namespace Shop, a class name can take three forms:

  • Unqualified, such as Invoice. PHP puts the current namespace in front, giving Shop\Invoice.
  • Qualified, such as Billing\Invoice. PHP still puts the current namespace in front, giving Shop\Billing\Invoice.
  • Fully qualified, such as \Shop\Billing\Invoice. The leading backslash means start at the root. The name is used literally.

The next example puts two classes in different namespaces and refers to them in all three ways. It uses the braced namespace form, where each namespace has its own block.

Example
<?php
namespace Shop\Billing {
    class Invoice
    {
        public function label(): string
        {
            return 'billing invoice';
        }
    }
}

namespace Shop {
    class Invoice
    {
        public function label(): string
        {
            return 'shop invoice';
        }
    }

    $a = new Invoice();
    $b = new Billing\Invoice();
    $c = new \Shop\Billing\Invoice();

    echo $a::class, ': ', $a->label(), "\n";
    echo $b::class, ': ', $b->label(), "\n";
    echo $c::class, ': ', $c->label(), "\n";
}
Output
Shop\Invoice: shop invoice
Shop\Billing\Invoice: billing invoice
Shop\Billing\Invoice: billing invoice

The qualified name and the fully qualified name end up at the same class. The unqualified name stays in Shop.

Reaching global classes

Built-in classes such as Exception live in the global namespace. Inside a namespace, an unqualified Exception means a class in your own namespace. To reach the built-in one, write \Exception.

Example
<?php
namespace App;

class Exception extends \Exception
{
}

$local = new Exception('local');
$global = new \Exception('global');

echo $local::class, "\n";
echo $global::class, "\n";
echo $local instanceof \Exception ? 'yes' : 'no', "\n";
Output
App\Exception
Exception
yes

The two classes are different, but the local one extends the global one, so the instanceof check succeeds.

Functions and constants behave a little differently. An unqualified function or constant name falls back to the global one if no namespaced version exists. Classes have no such fallback. Writing \strlen() is still a clear way to say that you mean the global function.

Worked reasoning

Take the current namespace App and the name Models\User. It does not start with a backslash, so it is relative. The result is App + \ + Models\User, which is App\Models\User. Now take \Exception. It starts with a backslash, so you drop that first character and get Exception. If the code is global and the current namespace is empty, a relative name is already complete, so no prefix is added.

Exercise contract

Write resolveClassName(string $currentNamespace, string $name): string. It should return the full class name, without a leading backslash, that PHP would use:

  1. If $name starts with a backslash, return it without that first character.
  2. Otherwise, if $currentNamespace is an empty string, return $name unchanged.
  3. Otherwise, return the namespace, a backslash, and then the name.

The function treats unqualified and qualified names the same way, because both are relative to the current namespace.

Recap

A namespace prefixes class names so that similar names can coexist. Unqualified and qualified names are resolved from the current namespace, and a leading backslash starts from the global root. Use \Exception or \strlen() when you mean the global element.

Before you start

Classes

You’ll practice
  • Declare a namespace
  • Refer to a class with a fully qualified name
Your task

Make resolveClassName() pass all 5 checks. Run your code as often as you like, then check your answer.

exercise.phpSaved in this browserPHP 8.5
CONSOLE & CHECKS● Ready

Ready when you are

Your output will appear here.
Make it work. Then make it pass.

PHP loads on your first run. Each check starts fresh. Your code stays in this browser; clearing site data removes your progress. A check or the task looks wrong? Report a problem with this exercise.