Magento – How to run Magento 2 from a subdirectory

magento2nginx

I'm trying to set up a Magento 2 site that will run with http://www.example.com/store/ as its home page, but Magento's router is treating that subdirectory path as a frontend module name, and trying to run a module called store that doesn't exist.

My base URLs are configured as such:

mysql> select * from core_config_data where path like '%url';
+-----------+---------+----------+-----------------------+-------------------------------+
| config_id | scope   | scope_id | path                  | value                         |
+-----------+---------+----------+-----------------------+-------------------------------+
|         2 | default |        0 | web/unsecure/base_url | http://www.example.com/store/ |
|         3 | default |        0 | web/secure/base_url   | http://www.example.com/store/ |
+-----------+---------+----------+-----------------------+---------- --------------------+

With this setup, I updated the Nginx config, altering the location declarations to include /store at the beginning. Once that was done I was able to access the site and static assets were loading properly, however any page I tried to access resulted in Magento's fancy 404 page.

Since I knew the request was making it into the Magento app, I had a hunch that Magento's routing was causing the issue. To test, I created a new module with a simple controller at /app/code/MyModules/Store/Controllers/Index/Index.php, and gave it a router with a frontName of store. Once I activated that module and reloaded the page, instead of a 404 I got the simple JSON output I had set up in my custom controller. So I know that Magento is getting the request and thinks the initial subdirectory that is part of its base URL is actually a frontName route.

So at this point I have two questions:

  1. Is it even possible to run a Magento 2 store in a subdirectory like this, or do I have to resort to using a subdomain?
  2. Assuming the answer to 1 is "yes, it is possible", what am I missing to make this work? I feel like there must be some setting somewhere that will resolve this, but I simply don't know where to look anymore.

Update with more details:

Since several people have made suggestions related to the actual location of the Magento application files on my server, I want to clarify that I'm running the Magento site on its own server, and using Nginx to proxy requests matching the /store path from my base server to this one. I don't think that this setup is causing any problems, but I suppose it's possible.

I also went through another diagnostic attempt, to make sure the problem is indeed where I think it is. I'll detail those steps and their results below.

  1. I updated my proxy server to send all traffic on store.example.com to the server running Magento.
  2. I updated the base URLs in core_config_data to http://store.example.com. Once this was done, I was able to access the Magento site and it behaved normally.
  3. I logged in to the Magento admin area and updated the URLs via the UI, changing both the secure and unsecure URLs to http://store.example.com/store/.
  4. Once I clicked "save" on the settings, the page reloaded and the URL changed from store.example.com/admin/admin/system_config/edit/... to store.example.com/purchase/admin/admin/system_config/edit/..., and 404ed.
  5. The basic module that I'd created earlier (with a frontName of store) still worked, and was the only page I was able to load without a 404.
  6. Further attempts to access the site on store.example.com/ were redirected to store.example.com/store/

What this tells me is Magento understands that it has a new base URL (thus the redirects to /store/), but that there is still some additional setup or configuration somewhere that must be missing, since the router is still trying to interpret that part of the URL path. Is there a separate setting for the router base path that's different from the website base URL maybe?

Update 2: The Second

I got this working in a way that feels much more like a "hack" than a solution. I've detailed that method in an answer below.

Best Answer

If you are trying to create a store only then you need to copy index.php and .htaccess from main website and then change path of

require __DIR__ . '/app/bootstrap.php';

To

require '../app/bootstrap.php';

Then change $params value

$params = $_SERVER;

$params[\Magento\Store\Model\StoreManager::PARAM_RUN_CODE] = '<store_name>';

$params[\Magento\Store\Model\StoreManager::PARAM_RUN_TYPE] = 'website';

.htaccess :

## path relative to web root

#RewriteBase /magento/

SetEnvIf Host .*<store_name>.* MAGE_RUN_CODE=<store_name>

SetEnvIf Host .*<store_name>.* MAGE_RUN_TYPE=website

OR

Update index.php from pub folder

<?php
/**
 * Public alias for the application entry point
 *
 * Copyright © 2013-2017 Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

use Magento\Framework\App\Bootstrap;
use Magento\Framework\App\Filesystem\DirectoryList;

try {
    require realpath(__DIR__) . '/../app/bootstrap.php';
} catch (\Exception $e) {
    echo <<<HTML
<div style="font:12px/1.35em arial, helvetica, sans-serif;">
    <div style="margin:0 0 25px 0; border-bottom:1px solid #ccc;">
        <h3 style="margin:0;font-size:1.7em;font-weight:normal;text-transform:none;text-align:left;color:#2f2f2f;">
        Autoload error</h3>
    </div>
    <p>{$e->getMessage()}</p>
</div>
HTML;
    exit(1);
}

$params = $_SERVER;
$params[Bootstrap::INIT_PARAM_FILESYSTEM_DIR_PATHS] = [
    DirectoryList::PUB => [DirectoryList::URL_PATH => ''],
    DirectoryList::MEDIA => [DirectoryList::URL_PATH => 'media'],
    DirectoryList::STATIC_VIEW => [DirectoryList::URL_PATH => 'static'],
    DirectoryList::UPLOAD => [DirectoryList::URL_PATH => 'media/upload'],
];

switch($_SERVER['HTTP_HOST']) {
    case "<domain>":
        $params[\Magento\Store\Model\StoreManager::PARAM_RUN_CODE] = '<store_code>';
        $params[\Magento\Store\Model\StoreManager::PARAM_RUN_TYPE] = 'website';
        break;
}


$bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $params);
/** @var \Magento\Framework\App\Http $app */
$app = $bootstrap->createApplication('Magento\Framework\App\Http');
$bootstrap->run($app);
Related Topic