Laravel 101 - Namespaces

To understand how to structure your application, you must understand namespacing.

Namespaces

Imagine you are writing a CMS for a school website, you might have a class for the CMS user Admin that controls the site, and also Admin that represents some school staff members. And let's say there's a 'Staff Directory' page you need to update because the school just hired a new administrator. When you add a new staff member into the database, how will your application know which Admin you're talking about? The answer is to use namespace.

Generally speaking, only one entity can exist with a particular name in a particular scope. So having two classes both named Admin within the same scope is no good. In essence, a namespace defines a scope; so the two Admin classes need to have different namespaces.

Put it another way, namespacing is a way to organize your classes and functions so their names do not conflict. It provides the classes and functions with some extra information to distinguish them from each other.

So, using the example above, our namespaced classes might be

Cms\Roles\Admin
Staff\Admin

Namespace is used extensively in Laravel, the Application and Kernel classes are just some examples of its use.

Illuminate\Console\Application
Illuminate\Foundation\Application

Illuminate\Foundation\Console\Kernel
Illuminate\Foundation\Http\Kernel

PSR-4

PSR-4 is a specification for autoloading classes from file paths. The idea is that you simply place your classes, interfaces or traits in a PSR-4 standardized file structure, and the autoloader will load them for you.

Each fully qualified class consists of one vendor (or root) namespace, optional sub-namespaces, and a classname.

\<NamespaceName>(\<SubNamespaceNames>)*\<ClassName>

The vendor namespace will be associated with a base directory, subnamespaces specify sub-directories within the base directory, and class names corresponds to filenames ending in .php in those directories. All directories and file names are case-sensitive.

For example, the class Controller with the namespace Techwork\Http\Controllers can have a vendor namespace of Techwork and sub-namespace of Http\Controllers, and is located at app/Http/Controllers/Controller.php

Why PSR-4?

Having a standard way of organizing your namespaces and classes means now we can automate a lot of tasks, such as autoloading classes. Furthermore, it will be more understandable for other developers working on it.

Namespaces in Laravel

If we look inside the our composer.json file, we will find an object with the autoload.psr-4 property.

"autoload": {
  "classmap": [
    "database"
  ],
  "psr-4": {
    "App\\": "app/"
  }
},

Here, we're telling Composer to register an autoloader for the App namespace using the PSR-4 specification. Thus, by default, your application resides within the app/ directory and namespaced under App.

The autoload.classmap array specifies directories where you can make additional classes available to your app

vendor/composer/autoload_psr4.php is where the actual namespace-directory pairs are stored. A look inside you'll find it returns an array of these pairs.

'Illuminate\\' => array($vendorDir . '/laravel/framework/src/Illuminate')

Thus, the base directory for the Illuminate class is vendor/laravel/framework/src/Illuminate (where $vendorDir corresponds to vendor/). So we should expect to find Illuminate\Foundation\Http\Kernel at vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php, and indeed we do.

Changing Namespace

We can change our namespace easily with an Artisan command. My app is called Techwork.

$ php artisan app:name Techwork
Application namespace set!

Now, when we check back into our composer.json file, App has changed to Techwork.

"psr-4": {
    "Techwork\\": "app/"
}

Running app:name changes a lot of files, so do not attempt to manually change namespace yourself; use the Artisan command.

If you have trouble setting app:name at subsequent times, this is because Composer still has the autoload files at the vendor/composer/ directory with information regarding your namesapce. So run composer dump-autoload -o, which will clear your namespace entries and you can try running app:name again.

Also ensure you have the latest version of Composer by running composer self-update.

comments powered by Disqus