Using the Use Statement with Namespaces

Understanding how the use statement works with namespaces to save having to type out long namespace names.

By Bob Ray  |  December 23, 2024  |  3 min read
Using the Use Statement with Namespaces

In the previous article, we looked at how to use namespaced classes in code. In this one, we'll see how to use the use statement to streamline code that uses namespaced classes.

We'll continue to use the VeterinaryOffice project from the previous articles. For review, here is its structure:


/* PROJECT_BASE_PATH is a constant that will be set to the full path of the VeterinaryOffice directory; it must end with a slash */ PROJECT_BASE_PATH src/ Controllers/ Controller.php Model/ Pets/ Dog.php Cat.php

Namespaces: Overview

The use statement provides shorter aliases for namespaced classes and constants. Including use statements is also calls "Importing," but the term is misleading. The use statement simply provides an alias for the class, it doesn't really "import" anything. You'd still have to include or require the class file unless you have an autoloader (more on autoloaders in upcoming articles).

A use statement is very simple and easy to understand, in spite of some confusing descriptions you might see. There are just two forms for the use statement. Here are examples based on the example namespaced files we saw in the previous article:

use VeterinaryOffice\Model\Pets\Dog;
use VeterinaryOffice\Model\Pets\Dog as Canine;

The first form above just tells PHP that when you use the part after the last backslash, you mean the whole path. In other words, Dog will be an alias for VeterinaryOffice\Model\Pets\Dog.

The second form, as you've probably guessed, says that Canine can be used as an alias for the fully qualified class name. With just the second form above, you can no longer use Dog as an alias, but there's nothing stopping you from using both the use statements above. In that case both Dog and Canine will be aliases for the fully qualified class name, VeterinaryOffice\Model\Pets\Dog.

As we mentioned in the previous article, aliases/imports will not work with class_exists() because its argument is a string. When calling class_exists() with namespaced classes, you need to use the fully qualified class name in the argument.

In the PHP code I've looked at, the second form (with "as") is seldom used. I would only use that form if either 1) the name of some third-party class used in my code had a misleading or uninformative name, or 2) due to included third-party files, there were two classes with the same name.

Using Aliased Namespaces

By using namespace aliases, we can make the code that uses our namespaced classes more compact and easier to read. We'll show the new code below, but first a review of the namespaced Dog, Cat and Controller class files. Only the Dog class has changed.

These files would not have to change at all, but we've added the two constants we mentioned in the previous article to the Dog class file, so you can see how they work in context, and in our new code, we've added lines to display them.

And we've added the outsideFunction() function at the end of the Dog class file to demonstrate how the use statement works with functions.

The Dog class file is the only one that has changed, and all of its original code remains unchanged. We just added a few things.

Dog Class

<?php

namespace VeterinaryOffice\Model\Pets;

const OUTSIDE = 'Outside constant';

class Dog {
    const INSIDE = 'Inside constant';

    function __construct() {
      /* constructor code here */
    }
    function speak() {
        return 'arf';
    }
}
/* Outside any class */
function outsideFunction() {
    echo "\noutsideFunction";
}

Cat Class

<?php
namespace VeterinaryOffice\Model\Pets;

class Cat {
    function __construct() {
      /* constructor code here */
    }
    function speak() {
        return 'meow';
    }
}

Controller Class

<?php
namespace VeterinaryOffice\Controllers;

class Controller {
    function __construct() {
        /* constructor code here */
    }

    public static function sayHello() {
        echo "\nController Says Hello!";
    }
    /* Other controller methods here */
}

The New Code

Here's some code that uses our new, namespaced classes.

<?php
namespace VeterinaryOffice;

use VeterinaryOffice\Model\Pets\Dog;
use VeterinaryOffice\Model\Pets\Cat;
use VeterinaryOffice\Controllers\Controller;
use const VeterinaryOffice\Model\Pets\OUTSIDE;
use function VeterinaryOffice\Model\Pets\outsideFunction;

/* Note: PROJECT_BASE_PATH needs to end in a slash (/) */
const PROJECT_BASE_PATH = 'full/path/to/VeterinaryOffice/';

$basePath = PROJECT_BASE_PATH . 'src/';
require $basePath . 'Model/Pets/' . 'Dog.php';
require $basePath . 'Model/Pets/' . 'Cat.php';
require $basePath . 'Controllers/ . 'Controller.php';
echo "\n" . OUTSIDE;

if (class_exists('VeterinaryOffice\Model\Pets\Dog', false)) {
    $dog = new Dog();
}
echo "\n" .  $dog::INSIDE;

if ($dog && ($dog instanceof Dog)) {
   echo "\nDogs say: " . $dog->speak();
}

if (class_exists('VeterinaryOffice\Model\Pets\Cat', false)) {
    $cat = new Cat();
}

if ($cat && ($cat instanceof Cat)) {
   echo "\nCats say: " . $cat->speak();
}

if (class_exists('VeterinaryOffice\Controllers\Controller', false)) {
    $controller = new Controller();
}

if ($controller && ($controller instanceof Controller)) {
   $controller::sayHello();
}

outsideFunction();

Here's the output of the code above:

Outside constant
Inside constant
Dogs say: arf
Cats say: meow
Controller says Hello!
outsideFunction

With the exception of the calls to class_exists(), our new code is a lot simpler and easier to read (and to type). The aliases created by the use statements allow us to use code that looks just as it would if there were no namespaces. Instead of VeterinaryOffice\Model\Pets\Dog, we can just use Dog.

The code above will work as written with, or without, the namespace declaration at the top, because the aliases cover all the classes used in the code, and all the calls to class_exists() use a fully qualified class name.

Notice that the use statements (near the top of the code) for constants and functions have to start with use const or use function. Without those, a use statement is assumed to apply to a class or interface.

A use statement can go anywhere in the code, as long as it is above any place that makes use of its namespace alias, and multiple use statements don't have to be together. It's a good practice, though, to put them all together near the top of the code (below the namespace declaration, if there is one) to make them easier to find and to offer a preview of the classes used in the code below them.

In my next article, we'll take a look at creating and registering an autoloader.


Bob Ray is the author of the MODX: The Official Guide and dozens of MODX Extras including QuickEmail, NewsPublisher, SiteCheck, GoRevo, Personalize, EZfaq, MyComponent and many more. His website is Bob’s Guides. It not only includes a plethora of MODX tutorials but there are some really great bread recipes there, as well.