3

I need to deploy a publicly accessible PHP file as part of a Magento 2 extension. Obviously this is not intended, as usually all requests should be routed through index.php, but in this case it's needed for performance optimization.

Is it possible to do this without requiring manual installation steps (i.e. copy files to /pub)?

I thought about making it a static asset, but the PHP engine is disabled by default in pub/static for good reasons.

Can I use the Magento composer installer in some way?

8
+100

First part is how to do this from an extension builder perspective. I'm leaving the second part as reference for project builders.

Extension builder answer:

You can't do this from within an extension which has

...
"type": "magento2-module"
...

in its composer.json file.

You will need to create a new/extra extension for these files. This new extension will have a composer.json as follows:

{
    "name": "vendor/magento-module-foomodule-files",
    "description": "Extra files for vendor/magento-component-foomodule",
    "require": {
        ...
    },
    "type": "magento2-component",
    "extra": {
        "map": [
           "pub_scripts/*",
           "pub_scripts"
        ]
    ]
}

Update your module's composer.json to require this new extension:

{
    "name": "vendor/magento-module-foomodule",
    ...
    "require": {
        "vendor/magento-module-foomodule-files": "*"
    }
    ...
}

During installation all files from /path/to/webroot/vendor/Vendor/magento-module-foomodule-files/pub_scripts/ directory will be copied to /path/to/webroot/pub_scripts/

Project builder answer:

You will have to write your own post install commands for composer. This is relatively simple though. Add the 'scripts' node to your composer.json as follows:

    ...
    "scripts": {
        "post-install-cmd": [
            "scripts/post-install-cmd/deploy.sh"
        ]
    }
}

Note: this is the composer.json file in the root of your project.

And the script itself: scripts/post-install-cmd/deploy.sh

#!/bin/bash

WEBROOT=/path/to/webroot

#copy file(s) (never move files away from vendor)
cp "${WEBROOT}/vendor/Vendor/Module/files/file1.php" "${WEBROOT}/pub_scripts/file1.php"
cp "${WEBROOT}/vendor/Vendor/Module/files/file2.php" "${WEBROOT}/pub_scripts/file2.php"

In this example I copy the files to the 'pub_scripts' directory. This directory will need to exist.

  • Replace Vendor/Module in the file path with you own values of course.
  • Make sure that files in the 'scripts' and 'pub_scripts' directories are not publicly accessible. Deny all access to the 'scripts' directory and use htaccess login and/or IP whitelist for the 'pub_scripts' directory.

Your script(s) are now available for you at

  • 1
    Works like a charm, I can even replace "pub_scripts" with "" to deploy directly to the document root. Actually I used both "pub" and "" as target because the document root might be "pub" as well. – Fabian Schmengler Oct 6 '16 at 12:38
  • 1
    "pub_scripts" was completely arbitrary :) basically whatever you use will map to the document root – Vincent Hornikx Oct 7 '16 at 9:02
  • Can you tell me the folder structure, how to keep that external php file in my package folder.( I mean inside my zip file which I will upload in marketplace) – Gaurav Agrawal Mar 9 '17 at 11:44
  • @FabianSchmengler Can you please guide me to create my composer file. – Gaurav Agrawal Mar 10 '17 at 5:17
  • @GauravAgrawal I don't think you can upload the two(!) packages to the marketplace together. You probably need to put the one with the public scripts to github and add it as dependency. – Fabian Schmengler Mar 11 '17 at 8:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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