Load modules and themes from src in Magento 2

Posted February 7, 2016

One of the biggest changes for me in Magento 2 is the fact that we no longer have code pools app/code/local etc. This represents a massive shift forward and a great design decision by the Magento 2 core team to adopt the composer autoloader.

Now for shared modules the logic is easy, You create you composer.json manifest file and in the mappings specify via PSR-4 where you want the namespace to resolve to. Then when someone wants to use the module they updated the main projects composer.json manifest and the rest is magic.

But what about the Companies or Solution integrators that use a mixture of both community modules and also develop single use modules. How can a project setup look with PSR-4 support and one off module development.

Well I started to explore how this might look here I see this as being the starting point for any company working with Magento 2. Some points to note are that I am not adding Magento 2 to the repository. Why ? Well I don’t own this code. Its not my code. Im using composer to manage by dependencies for me and always committing the composer.lock file that has the versioned pinned to a specific release so really if I do add Magento 2 code to my repository I am duplicating effort.

Next up you will see that I am adding my code into a src folder. Why again ? Well I could use app/code/NAME if I wanted and this will just work out of the box ( as long as the module I work on has a registration.php file). Yet I wanted to try and follow the same process that other PHP frameworks use Symfony, Laravel etc and this is using the src folder. Now the first attempts add just adding a composer.json file in the module with a registration.php file failed. I even tried updating the PSR-4 and PSR-0 references in the main projects composer.json manifest to resolve the mappings but what I noticed was that a special file created by composer autoload_files did not have the mappings for my single use modules registration.php.

So how did I resolve this. Well:

"autoload": {
        "psr-4": {
            "Magento\\Framework\\": "lib/internal/Magento/Framework/",
            "Magento\\Setup\\": "setup/src/Magento/Setup/",
            "Magento\\": "app/code/Magento/",
            "Jcowie\\HelloWorldModule\\": "src/Jcowie/HelloWorldModule/"
        },
        "psr-0": {
            "Jcowie\\HelloWorldModule\\": "src/Jcowie/HelloWorldModule/"
            "": "app/code/"
        },
        "files": [
            "app/etc/NonComposerComponentRegistration.php",
            "src/Jcowie/HelloWorldModule/registration.php"
        ]
    },

I started by adding the namespace mappings to both the PSR-4 autoloader and the PSR-0 autoloader this is so that composer can find the source files for Jcowie\HelloWorldModule when called upon. Then the important part that I was missing is in the files section. This is how the autoload_files.php gets populated and for every custom ( non composer installed ) module you wish to write you need to add its reference in here. Then running composer dump-autoload checking the files and running my module from the src directory resulted in success.

So why is this such an important win ? Well if you look at the repository then it is a lot cleaner just having the files I own added to the project. Also it keeps the revision history nice and clean, When I upgrade Magento 2 versions I only see the difference in the composer.json and composer.lock files and not a large diff of all the Magento 2 core files that have changed. It also follows on from what other PHP frameworks are doing using the src folder so interoperability between projects can exist.

You may also find these related posts interesting: Patching Magento 2 vendor directory Technical Insights into Magento 2 Continously delivering Learn to love testing an agile journey into Behat, PHPSpec and Magento