I've added a local development module (separate git repo) to Magento 2 using symbolic links and it was working fine until I hit the PHTML templates. After heavy debugging I found out that the Magento 2 filesystem class (Magento\Framework\Filesystem\Directory\Read) uses an isExists() method combined with an getAbsolutePath() call to see whether the PHTML template exists. However, the getAbsolutePath() method checks whether the relative path exists within the Magento 2 filesystem and if not, it prepends the Magento 2 root to. it. In my case, the module lives in a separate repo /git/A while Magento lives in /site/B and this behaviour checks for the existence of a PHTML template in /site/B/git/A.

In short: PHTML templates that live outside of the Magento 2 root filesystem are not picked up, regardless of the System Configuration setting "Allow Symlinks" being turned on. It seems that setting is working, but only if the source of the symlink is still within the Magento 2 filesystem.

Has anybody else encountered this? What would be the best way to handle development in an external git repo?

  • 50/50 bug/feature. I say file an issue.
    – benmarks
    Commented Dec 26, 2015 at 12:06
  • @benmarks this is known issue which has a workaroud, see my answer Commented Dec 27, 2015 at 9:23

5 Answers 5


Hackish workaround if you are using composer path repository for your module.

In registration.php put:

    isset($file) ? dirname($file) : __DIR__

This will register your module under symlinked path in Magento's root vendor dir instead of its real path.

  • 1
    This solution worked for me until I upgraded to Magento 2.3 (I'm getting 'Invalid Template File...' error). Any idea how to solve it?
    – Pini
    Commented Dec 13, 2018 at 14:50
  • Sorry, no. Are you sure this works when you are not using symlink? If so you would have to debug how M2.3 is loading templates. Maybe open another question?
    – fsw
    Commented Dec 14, 2018 at 10:55
  • It's working without the symlink.
    – Pini
    Commented Dec 16, 2018 at 9:07
  • I use Vagrant during development. I symlink /vagrant/app/code/Vendor/ to /var/www/shop/app/code/Vendor. This solved it for me! Commented Dec 14, 2019 at 3:49
  • I'm back. This solution does not work. When I used this to symlink my module code the adminhtml routes for my module wouldn't work. I confirmed this by removing the symlink and copying the files over to the app/code directory. The plugin then worked. You can confirm by creating this module and symlinking it: devdocs.magento.com/guides/v2.3/ext-best-practices/… ... you'll get the same problem I had. Commented Dec 18, 2019 at 15:22

It is possible to enable/allow symlinks thru the Stores => Configuration => Advanced => Developer => Template Settings (just like in Magento 1.x):

Configuration option

(I did not test if this setting works)

Also you can use submodules, this way you don't need symlinks.

For development, I develop modules in a separate directory and use PHPStorm to copy them into my develop installation of Magento 2.

  • 1
    Thanks. The setting I mentioned was indeed the "Allow Symlinks" setting under "Template Settings". It works nicely under Magento 1.x, but now under Magento 2, the files need to be within the Magento root, so not just anywhere on the filesystem. Anyway, I'll be fine - I'm probably going to use submodules :) Commented Dec 26, 2015 at 13:58
  • Jisse, just a thought...you can also use composer to assemble separate modules when you produce your build artifacts, which tends to avoid some of the issues you may run into with git submodules, though it may add to the complexity of your build process. AFAIK, this is Magento's recommended way to handle the situation. Commented Dec 26, 2015 at 14:55
  • Thanks, the PHPStorm options already solved it for me, but as @alex-paliurush pointed out, there are some scenarios where the workaround simply does not work. I'll add a PR instead. Commented Dec 29, 2015 at 17:25
  • Thanks Bryan for your suggestion as well. However, composer is perfect when dealing with production sites, but I was looking for a better way to develop custom modules. Composer should not yet be in play, because it is the way to distribute the code that I need to develop within Magento 2 first, so composer is always various commits behind. That being said, PhpStorm (and other IDEs) already offer a solution for this. So the only issue that remains is that production sites suffer from this symlink limitation, and then your arguments kick in :) Commented Dec 30, 2015 at 8:53

To allow symlinks, run:

bin/magento config:set dev/template/allow_symlink 1

To fix the path to template file being outside the application root, change your registration.php to register the module using the $file variable defined in etc/NonComposerComponentRegistration.php.

Guard this with checking that $file is defined and points to your registration.php in case it is ever loaded in a different way.

use Magento\Framework\Component\ComponentRegistrar;

    isset($file) && realpath($file) == __FILE__ ? dirname($file) : __DIR__

If you develop using PHP Storm, just copy second repository to the Magento project root. Then create necessary symlinks to enable module. PHP Storm will treat this project as multirooted and will recognize both repositories. You may choose between synchronous and asynchronous (default) repository management strategies.

This issue also happens when EE (or any other module) is linked to CE using symlinks. The root cause is that registration.php calculates base module path as real path to directory (in your case it is outside the Magento project). That is why relative path is calculated incorrectly, and then absolute path is incorrect as well. If second repository is put under Magento root, relative path would point to real file path (not symlink), but it would still be found, so everything will work.


It should also be possible to manipulate the registration.php to point to your dev root.

To make sure it's getting loaded, you would have to execute the registration.php somewhere in your bootstrap process.

The easiest way (without installing it via composer) would be to add it manually to the vendor/composer/autoload_files.php.

I also thought about writing a module for this. This module could also be Useful for integration test environments (for adding and removing modules on the fly without having to copy them somewhere).


by now I wrote the module: http://github.com/davidverholen/magento2-dynamic-component-registry

also I think it should be possible to link modules using relative symlinks


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.