Over a million developers have joined DZone.

How to Add Composer Compatibility to Magento 2 Backend Launcher?

DZone's Guide to

How to Add Composer Compatibility to Magento 2 Backend Launcher?

Free Resource

 Are you planning on developing a Magento 2 module? Well, then you should be aware of the fact that a Magento 2 build cannot run without a composer. In essence, you'll have to add Composer compatibility to your module. In this post we will look at the process of making the Composer compatible with a Magento module. But, before that let's first understand what is a composer.

What exactly is a Composer?

It's a tool that performs dependency management in PHP. A Composer enable users to declare dependent libraries for a Magento project, and help install the libraries in the project.

Making the Module Compatible With Composer

If you're not making the Backend Launcher module compatible with the composer, you may encounter a problem. The launcher module throws the following exception in the Magento 2 backend.

Fatal error: Call to a member function setActive() on a non-object in \magento2\htdocs\app\code\Magento\Backend\App\AbstractAction.php on line 155

You can take a few steps backwards through the application run manually and figure out the cause of exception, However, this can be a monotonous and tiresome process. But there is another way that can help you achieve the same quickly, what you need to do is to check out the code base and see if you can recognize anything that changed in the new Magento 2 build. For this purpose, we will have to abide by the following steps:

New Default Layout Definition

Since the code base comprises of only one block along with a few assets, in the first step we'll begin with inspecting if the problems in the newer Magento 2 build occurs due to the addition of the block and assets or not. For doing so, we will need to open “view/adminhtml/layout/default.xml” file. This will help us access the default layout file, and will disclose whether the schema definition referenced to exist or not.

The newer Magento 2 builds could have either renamed, substituted or got rid of the “Magento/Core/etc/layout_single.xsd” file referenced to. This is because newer builds most likely would have changed the XML structure in some way. And so, in order to find out the newer build, we need to look for a module having the similar objective – that is to add an interface element to the header – just like the Launcher module does.

Magento_AdminNotification is the module that helps to fulfill the same objective as that of the Launcher module. Open the default.xml file of the “Magento_AdminNotification” module, and we will be able to quickly spot the difference. You'll see that the root tag will become a page instead of a layout. And the 'default.xml' layout definition of the Launcher gets replaced with the correct one, such as:

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">

Reloading the backend will still deny you from showing the Magento 2 dashboard. But in this case, a direct exception won't be thrown, rather you'll receive a friendly message stating that: something isn't right with the schema definition and a fresh error log has been produced. You will be able to understand the top-level exception of the error log:

Invalid block type: Magento\Theme\Block\Html\Head\Script

Understanding a New Way to Adding Assets

The above exception is clear: an attempt is made to add a block that no longer exist. However, this issue was fixed in Magento community edition – 0.1.0-alpha97. Moreover, now the “page configuration API” is used for managing the assets.

At present, the documentation on page assets is out-of-date and you we didn't tried to look out for any other documentation on the aforementioned API. But, there's nothing that you should worry about, you can simply we can simply plunge into an already present Magento 2 module to reveal how asset management is taken care of.

In the beginning, you'll have to get rid of the node <referenceContainer name="head"> completely. This will ensure that at least the backend is working. Next, scrutinize the rendered HTML and choose a JavaScript and/or CSS file that you want to look out for. In our case, we will go with Magento_Rule: rules.js. You'll find it in the default.xml in the Magento backend.

<link src="extjs/ext-tree-checkbox.js"/>
<css src="extjs/resources/css/ext-all.css"/>
<css src="extjs/resources/css/mynewtheme-magento.css"/>
<link src="Magento_Rule::rules.js"/>

You'll encounter a coupling issue in the above code, but luckily you'll now be aware of how the new syntax looks like. And so, we will update our Launcher module along with its default.xml accordingly:

 <?xml version="1.0"?>
<page [...]>
<link src="OSSMedia_Launcher::js/launcher.js"/>
<css src="OSSMedia_Launcher::css/launcher.css"/>

An Overview of the New Syntax: As you can see in the code above, a JavaScript asset is referred to by a link tag, while a css tag is used for referring to CSS assets. What's more? You might find the picked names somewhat confusing: In HTML, CSS files are enclosed within a link tag. In addition, irrespective of whether you're using either a link tag or CSS for either JS or CSS respectively will probably work – as Magento 2 will produce the correct HTML tag automatically.

Making a Minor Rename

Your Magento website backend will be working, and even your module and its assets will be included properly in the backend. In fact, you'll be able to see a plus-sign of your module in the admin panel. Till now everything will seem fine to you, until you'll actually need to use the module.

The problem you'll face is that the debug console will complain that the launcher_items variable hasn't been declared. This means that the block containing the Launcher items hasn't been included in the page that is being accessed. This might seem a bit strange to you, as everything appears to be fine; besides you didn’t even experienced any application-breaking exceptions. You can call it one of the benefits you get, by working with a codebase that's undocumented. However, on checking out the system.log thoroughly, you'll retrieve the following message:

Broken reference: the element 'before_body_end' is not defined

But, on inspecting the Magento backend page.phtml file you'll come to know that the before_body_end container is used even now:

<?php echo $this->getChildHtml('before_body_end') ?>

On further evaluation you'll find that reveals that the before_body_end container is defined again as before.body.end in all the page layouts of the Magento 2 backend. One possible reason due to which this problem is occurring may be because all dashes in 0.1.0-alpha97 in the container names are replaced by dots.

Once the container name is now written correctly in the default.xml layout definition, Magento will know exactly where the LauncherItems block needs to be placed.

Magento 2 Supports RequireJS

After making the change as discussed above, the debug console will still cause a JavaScript runtime error. Besides, the line that results in the runtime error will initialize the jQuery UI Autocomplete library as the input field on the Launcher.

Fortunately, Magento 2 started using RequireJS in Though, the implementation was at the beginning level during the initial development on, however, with the latest Magento 2 build RequireJS will be responsible for loading jQuery UI. And so, we will not be able to call “.autocomplete” until we're sure that the UI library is fully loaded. Next, the jQuery document.ready callback wraps up in a require() callback indicating a jQuery UI library dependency:

 jQuery(document).ready(function($) {
require(['jquery/ui'], function(ui) {
source: launcher_items,

That's it, the Launcher module will be up and running by now.

Adding Composer Compatibility

Now, we'll have to add Composer compatibility to the Backend Launcher module. This is a simple and straightforward process. Composer works with a plenty of package sources. Since Magento 2 is in development phase, let's consider using Github as VCS repository. But later you can choose to cross-publish your packages to any other repository as well.

Let's use some existing module that exists in a Git repository, and use it to create a JSON file for any other project:

"name": "ossmedia/module",
"version": "0.0.1",
"type": "magento2-module",
"description": "This module embeds a launcher to the Magento 2 backend."

You can change name of the author, version, type and description etc. with the information as you deem perfect.

Even now, the require section seems to be a topic of debate, and you'll have to decide whether you should incorporate a Magento/framework reference, and refer to a package repository as well, such as “packages.magento.com”.

Let's forget about all the requirements till the time the entire “what-is-hosted-where” issue gets fixed up. In order to know, if the Magento 2 Composer installer is aware of the exact place where your files need to go, you'll require a map key. Below snippet will help create separation of the code and other project files, and thus, put the codebase of the Launcher module in an individual src directory.

"extra": {
"map": [

The mapping will result in deploying all the files in src/OSSMedia/Launcher to app/code/OSSMedia/Launcher.

Wrapping Up!

Hopefully reading this post will give you a basic understanding of how you can stay up-to-date about the Magento 2 codebase even as an outside developer. Most importantly, it will help you understand how you can add Composer compatibility to a Magento 2 module. In case you cannot perform the same task on your own, then you can choose to outsource Magento development.  This will help you get the job done at a lower cost.


Opinions expressed by DZone contributors are their own.


Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.


{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}