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 ?>