In the previous post we covered the basic of namespaces and CodeIgniter’s autoloader. Now lets dig a little deeper into namespaces and how we can use them in our applications.

Your Code, Organized Your Way

CodeIgniter provides a default layout structure for your application, but you can easily add and re-organize the code to fit your needs, with a very few restrictions. With classes namespaced now, it makes it very flexible to completely organize applications the way that works best for you or your company. Let’s look at a few different ways to use that your advantage.

Additional Directories

The easiest thing to do is to add a new directory to the application folder. You might do this to keep all of your Entity classes together, similar to how Models are stored together by default. This works out of the box. Simply create the directory, then any new files within that directory should be namespaced to include the new directory name.

After creating a new directory at application/Entities to store our Entity classes, we would use the following namespace for any Entities that you created: AppEntities. Whenever we need to get an instance of that class we would use:

$entity = new AppEntitiesNewsEntity();

That’s simple enough. Let's make some bigger changes.

Domain Mapping

Imagine a project that uses multiple classes for each domain of the application. If we are creating a forum application, we might have a PostModel, a Post entity class, a PostManager (that acts as a Repository class for Posts). We could completely change the structure of our application directory to reflect this, organizing our business logic classes by the application domain, instead of the class type. The application directory now might look more like:

application/
        Config/
        Controllers/
        Database/
        Domains/
            Forums/
                Forum.php
                ForumManager.php
                ForumModel.php
            Posts/
                Post.php
                PostManager.php
                PostModel.php
            Threads/
            Users/
        Filters/
        Helpers/
        Language/
        ThirdParty/
        Views/

This keeps all classes related to the business logic or data together. In this example, the controllers and views are kept in their default locations, but they could have been moved also. However, that makes things a little more complicated since we are dealing with modules at that point, and will be discussed in a later post.

Of course, all of the classes need to be correctly namespaced. So `Forum.php would use the namespace AppDomainsForums while Post.php would use the namespace AppDomainsPosts. Notice that the namespaces match the directory names and structure exactly.

New Namespaces

To organize any code outside of the application directory, the framework has to be told where to find the new files so it can map the namespace correctly. This could be used to keep your business logic code outside of the application directory, or to make a central place to store modules, for example. This is simple and requires adding a single line to application/Config/Autoload.php, in the $psr4 block of the constructor:

$psr4 = [
    'Config' => APPPATH.'Config',
    APP_NAMESPACE => APPPATH,
    'App'  => APPPATH,
    'Tests\Support' => TESTPATH.'_support',
    'Modules'  => ROOTPATH.'modules', 

In this example, a new namespace, Modules, has been defined. It can be found in a new directory modules that sits on the same level as the application and system directories. The constant ROOTPATH used here specifies the main directory that the project sits in. Other constants exist that can be used, also, though ROOTPATH and APPPATH will be the two most likely to be used.

Now you would might have several modules that you want to keep aside so that you can easily reuse them in other projects. This would make your Modules directory structure something like:

Modules/
        ModuleA/
            Config
            Controllers
            ...
        ModuleB/
            ...

Any controllers in Module A would have the namespace ModulesModuleAControllers.

This works fine, but it’s actually better to define a namespace for each module:

$psr4 = [
   'ModuleA'  => ROOTPATH.'modules\ModuleA',
   'ModuleB'  => ROOTPATH.'modules\ModuleB',
];

This allows your modules to take advantage a a few things the framework provides like automatic Service, Route, and Config file discovery for each of those modules. I will go into more detail on Modules in a future post.

Hopefully this inspires you to take the framework and make it work FOR you instead of thinking you have to be forced into the way it defaults to.


Did you like this post? Please consider becoming an Insider and supporting me here on Patreon and get even more in depth tutorials every month, as well as help keep the CodeIgniter 4 development moving forward at a good pace.