Defining & using PHP namespaces

Namespaces are simply a way for you to organize code. When your codebase gets much larger, namespaces can help you manage all of your classes. This can also help you out if you have multiple classes with the same name. By default, PHP uses one single global namespace, so if you create two clases with the same name, they will conflict with each other. However, defining namespaces in your app will compartmentalizing your classes, so the same class name can be used multiple times throughout your app, as long as they are each within their own namespace.

You define a namespace simply with the namespace keyword. It needs to be the first line in your PHP class.

For example, lets say we wanted the Author class to be in the App namespace. We can simply type namespace App at the top of this class:

<?php declare(strict_types=1);

namespace App;

class Author
{
    public function __construct(
        private string $name
    ) {}

    public function getName(): string
    {
        return $this->name;
    }
}

Let’s go back to the Post class, and we’ll notice something interesting. The Author class cannot be found. This is because it is no longer in the “global” namespace, but rather in the App namespace.

We can get things to work again by importing this class with the use statement, followed by the namespace & class name of the class we wish to use. This is essentially a “class import”. The value after namespace is known as the “fully qualified class name”. You may hear that term when you get deeper in your knowledge about classes in the future.

Now if we refresh our page, code will still work.

Let’s continue by adding a namespace to our Post class. We will put it in the same namespace as the Author class, App.

<?php declare(strict_types=1);

namespace App;

class Post
{
    ...

You’ll notice that the line importing our Author class, use App\\Author, is now grayed out. This is because both of these classes are now located in the same App namespace. Since they are at the same root of the same namespace, this import is unnecessary, as PHP will be aware of all classes in the same namespace. So we can remove this import class.

Finally, you will notice that our Post class is now grayed out. This is telling us that this class is no longer used anyplace. If we go back to our index.php file, we will see that PHPStorm is telling us that the Post class is undefined. This is because it is looking in the global namespace for this class, and that class no longer lives in the global namespace.

We can reference the Post class by it’s fully qualified class name by adding an App\\ to the beginning of each reference to it. This will get our code to resolve to the proper class.

<?php declare(strict_types=1);

require('classes/Post.php');

$title = 'My Blog';
$posts = App\\Post::getAll();
$numPosts = count($posts);
$postText = App\\Post::getText($numPosts);
$numPostsDisplay = "$numPosts $postText";
?>
<h1><?= $title ?></h1>
<h2><?= $numPostsDisplay ?></h2>
<?php for ($i = 0; $i < $numPosts; $i++) : ?>
    <h3><?= $posts[$i]['title'] ?></h3>
    <p><?= $posts[$i]['content'] ?></p>
    <p>By <?= $posts[$i]['author'] ?></p>
<?php endfor ?>

You can see that we are sortof repeating ourself in the code here though. If you had many references to different classes, it can be a bit verbose. So rather than referencing the fully qualified class name everyplace, you can instead import the class at the top of the file with the use keyword. This can make code a bit more tidy and easier to read.

<?php declare(strict_types=1);

require('classes/Post.php');

use App\\Post;

$title = 'My Blog';
$posts = Post::getAll();
$numPosts = count($posts);
$postText = Post::getText($numPosts);
$numPostsDisplay = "$numPosts $postText";
?>
<h1><?= $title ?></h1>
<h2><?= $numPostsDisplay ?></h2>
<?php for ($i = 0; $i < $numPosts; $i++) : ?>
    <h3><?= $posts[$i]['title'] ?></h3>
    <p><?= $posts[$i]['content'] ?></p>
    <p>By <?= $posts[$i]['author'] ?></p>
<?php endfor ?>


Complete and Continue