Magento2 modules outside of magento-root
Tags: magento2, php, composer
Published: 2018-05-22 18:22:08

---
title: 'Magento2 modules outside of magento-root'
published: true
canonical_url: https://www.mwltr.de/blog/2018/magento2-external-modules/
type: posts
tags: #magento2, #php, #composer
---

*This post was originally published on:* [https://www.mwltr.de](https://www.mwltr.de/blog/2018/magento2-external-modules/)

Quite recently I published a module which enables you to have your Magento2 modules outside of the magento-root.

{% twitter 991587881478172672 %}

If you missed it, here is the link to the module on github [mwr/ext-magento2-mwltr-filesystem-filedriver](https://github.com/mwr/ext-magento2-mwltr-filesystem-filedriver)

This post is meant as a follow up, to show you how to achieve a setup with external local modules and how to use this module.

# Prerequisites

Let's assume you want to achieve the following git repository directory-layout:

```
my-project
    ├── magento
    |   └── composer.json
    └── src
        └── namespace
            └── my-module
                └── composer.json
```

This setup would require your to run `composer install` inside the magento sub-directory of your project-root `my-project`.

This can be done from the project-root by executing `composer -d=magento install`.

The result will be magento copying its files inside the magento sub-directory.

# Adding modules from src

To include modules from outside of the magento-root `my-project/magento`, you have to do the following steps.

## Add local repository

Let composer know where to search for your local modules by adding the local repository.

You can do this by adding a json object to the repositories array with the type being `path` and `url` being the relative path to the modules.

```json
"repositories": [
    {
        "type": "path",
        "url": "../src/*/*"
    },
    {
        "type": "composer",
        "url": "https://repo.magento.com/"
    }
],
```

You can find more information about the repository of type path in the [composer documentation](https://getcomposer.org/doc/05-repositories.md#path)

## Add module require

After you have added the repository, you need to add the composer package name of the local module you want to require.

```json
"require": {
    ["..."],
    "my-namespace/my-local-module":"*"
}
```

If your run `composer -d=magento update` right now, you might run into an error stating that no suitable version can be found. 

![composer update error](https://thepracticaldev.s3.amazonaws.com/i/uryn73l01ti0r7j0fne2.png)

In this case you might have to adjust the `minimum-stability` setting to `dev` When you do that, I also suggest setting the `prefer-stable` flag.

```json
"minimum-stability": "dev",
"prefer-stable": true,
```

Now execute `composer -d=magento update` and the module `my-namespace/my-local-module` will be detected by composer.

![composer update success](https://thepracticaldev.s3.amazonaws.com/i/ryp6byq1cpjrdx58gymk.png)

Composer will create a symlink to your local module inside the `vendor/my-namespace` directory.

```bash
my-local-module -> ../../../src/my-namespace/my-local-module
```

## Issues with view or themes

If left like that the module it self will work from a backend point of view. But if you add a view with layout updates and templates to your module, this will fail due the limitations of the getRelativePath method in `\Magento\Framework\Filesystem\Driver\File`.

This is where my module [`mwltr/ext-magento2-mwltr-filesystem-filedriver`](https://github.com/mwr/ext-magento2-mwltr-filesystem-filedriver) comes into play. 
This module fixes the `getRelativePath`-implementation and generates a valid relative path.
It is a bit tricky since the di.xml won't work for the `\Magento\Framework\Filesystem\Driver\File` class. 
If you what to know more why that's the case have a look at the [README.md](https://github.com/mwr/ext-magento2-mwltr-filesystem-filedriver/blob/master/README.md) of the module.

The module is published on [packagist.org](https://packagist.org/packages/mwltr/ext-magento2-mwltr-filesystem-filedriver) so to require it add a require statement:

```json
"require": {
    ["..."],
    "mwltr/ext-magento2-mwltr-filesystem-filedriver": "^1.0.1", 
    "my-namespace/my-local-module":"*"
}
```

Now run `composer -d=magento update` again so the module is installed. 

You can also run 
`composer -d=magento require "mwltr/ext-magento2-mwltr-filesystem-filedriver"`
instead of manually updating the require section.

From here on, you can either install magento the way you know it or in case are updating an existing magento installation, go right away and add a module with a view part.

# Summary

Using this technique you can separate your project specific implementations from the magento-root or you can include external modules from any local path. 
Just be sure to think about the other developers working on that project, because they need the exact same paths, absolut paths or relative paths, on their machines as well.
It might be a good idea to not reference directories outside of you repository root, to prevent a whole new set of problems ;-).

The setup described in this post can be found on github: [mwr/demo-magento2-external-modules-simple](https://github.com/mwr/demo-magento2-external-modules-simple)

I am using a similar, slightly optimized setup for my projects and it works quite well.