Slim 3 cannot work in subdirectory. Cannot work when accessed from localhost/slim_app_dir

Created on 7 Oct 2015  路  14Comments  路  Source: slimphp/Slim

Hey Folks :)

Slim 3 cannot work in subdirectory. Cannot work when accessed from localhost/slim_app_dir.
BUT, no problem at all when using virtual host. I really really need to run slim 3 on sub directory.

I create / main route. It;s ok when accessed via virtual host.

$app->get('/', function ($request, $response, $args) {

    if (isset($_SESSION['Auth'])) {
        return $response->withStatus(302)->withHeader('Location', '/dashboard');
    }

    return $this->view->render(
        $response,
        'login/index'
    );
});

BUT, the route / never matched when accessed from localhost/slim_app_dir
Because the main url route, from / become /slim_app_dir
And I don't want to create url route named /slim_app_dir , because, i will crazy because i must create url route /slim_app_dir_renamed when i rename the directory.

Please help me
Thank you

Most helpful comment

I have a very simple fix for you to get Slim 3 running in a subdirectory:

I will show you how to fix the slim/slim-skeleton app:

  1. Create a new project (or take your existing project)
    cd c:\xampp\htdocs\
    composer create-project slim/slim-skeleton slim3-app

  2. Create a new file: c:\xampp\htdocs\slim3-app\.htaccess

Content of .htaccess

RewriteEngine on
RewriteRule ^$ public/ [L]
RewriteRule (.*) public/$1 [L]
  1. Fixing the script path

Open: c:\xampp\htdocs\slim3-app\src\dependencies.php

Add this lines to fix it:

<?php

// ....

$container['environment'] = function () {
    // Fix the Slim 3 subdirectory issue (#1529)
    // This fix makes it possible to run the app from localhost/slim3-app
    $scriptName = $_SERVER['SCRIPT_NAME'];
    $_SERVER['REAL_SCRIPT_NAME'] = $scriptName;
    $_SERVER['SCRIPT_NAME'] = dirname(dirname($scriptName)) . '/' . basename($scriptName);
    return new Slim\Http\Environment($_SERVER);
};

// ...

Now you can open the app via: http://localhost/slim3-app.

All 14 comments

Make use of Route names and pathFor, otherwise you will have to work out the context of subdirectories by yourself.

$app->get('/', function ($request, $response) {
    if (isset($_SESSION['Auth'])) {
        return $response->withStatus(302)->withHeader('Location', $this->router->pathFor('dashboard'));
    }

    return $this->view->render(
        $response,
        'login/index'
    );
});

$app->get('/dashboard', function ($request, $response) {
    return $response->getBody()->write('I am in the dashboard');
})->setName('dashboard');

Hi @silentworks ,
You do not understand what i mean. The app does not work on FIRST run. When accessed via subdirectory or http://localhost/slim_app_dir . I received Slim's 404 Page Not Found.

Every web app need a root url routing --> / as a their main page. In my case, the main root url routing can not be a / string. So.. in order to be able to have a root url routing as a main page, i must use /slim_app_dir/ as my root url routing to show my main page.

I'm not talking about handling http 301 redirection, including assetss (css, js, images) . I talk about accessing the app at FIRST run. The app failed to run at first. I received Slim's 404 Page Not Found. But, everything is ok when i access the app via virtual host. But i really really need to access the app via sub directory or http://localhost/slim_app_dir

this is my print_r($_SERVER);

[SERVER_SOFTWARE] => Apache/2.4.16 (Win32) OpenSSL/1.0.1p PHP/5.6.12
    [SERVER_NAME] => localhost
    [SERVER_ADDR] => 127.0.0.1
    [SERVER_PORT] => 80
    [REMOTE_ADDR] => 127.0.0.1
    [DOCUMENT_ROOT] => C:/xampp-php56/htdocs
    [REQUEST_SCHEME] => http
    [CONTEXT_PREFIX] => 
    [CONTEXT_DOCUMENT_ROOT] => C:/xampp-php56/htdocs
    [SERVER_ADMIN] => webmaster@vhost
    [SCRIPT_FILENAME] => C:/xampp-php56/htdocs/dev-spirit-back/webroot/index.php
    [REMOTE_PORT] => 51552
    [REDIRECT_URL] => /dev-spirit-back/
    [GATEWAY_INTERFACE] => CGI/1.1
    [SERVER_PROTOCOL] => HTTP/1.1
    [REQUEST_METHOD] => GET
    [QUERY_STRING] => 
    [REQUEST_URI] => /dev-spirit-back/
    [SCRIPT_NAME] => /dev-spirit-back/webroot/index.php
    [PHP_SELF] => /dev-spirit-back/webroot/index.php
    [REQUEST_TIME_FLOAT] => 1444270624.65
    [REQUEST_TIME] => 1444270624

I guess Slim 3 router depend on [REQUEST_URI] => /dev-spirit-back/ . So Slm 3 recognize /dev-spirit-back/ is the root url . Fyi, CakePHP Perfectly handle access via sub directory.

Here's how to reproduce it

  • just create a Slim 3 app skeleton
  • .htaccess setup
  • create root url routing $app->get('/', function () { ....
  • then access it by http://localhost/the_slim3_app
    You will receive Slim's 404 Page not found, until you rename / to /the_slim3_app/ .

Thank you :)

Just tested this following your steps and didn't have the issue you are currently having. Can you post your .htaccess file so I can see the rules you have set please?

@silentworks ,
wowww.. serious? did you use virtual host? you are not using virtual host, right?
I don't want to use virtual host.

Ok, this is my app structure

directory skeleton structure

C:\xampp\htdocs
---- slim3-app
-------- libraries
-------- protected
-------- public
------------ .htaccess
------------ index.php
-------- vendor
-------- .htaccess
-------- index.php

.htaccess at slim3-app/

RewriteEngine On

RewriteRule    ^$    public/    [L]
RewriteRule    (.*) public/$1    [L]

index.php at sli3-app/

<?php
require 'public/index.php';

.htaccess at slim3-app/public

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]

index.php at slim3-app/public

<?php
if (!defined('_ROOT_')) {
    define('_ROOT_', dirname(dirname(dirname(__FILE__))));
}

/**
 * The actual directory name for the "app".
 *
 */
if (!defined('_APP_DIR_')) {
    define('_APP_DIR_', basename(dirname(dirname(__FILE__))));
}

if (!defined('_DS_')) {
    define('_DS_', DIRECTORY_SEPARATOR);
}

if (!defined('_FULL_APP_PATH_')) {
    define('_FULL_APP_PATH_', _ROOT_._DS_._APP_DIR_._DS_);
}

require _FULL_APP_PATH_.'vendor'._DS_.'autoload.php';
require _FULL_APP_PATH_.'libraries'._DS_.'PlatesTemplate.php';
require _FULL_APP_PATH_.'libraries'._DS_.'Validator.php';
require _FULL_APP_PATH_.'libraries'._DS_.'PlatesUriExtension.php';
require _FULL_APP_PATH_.'libraries'._DS_.'PlatesFlashMessageExtension.php';
require _FULL_APP_PATH_.'libraries'._DS_.'PlatesFormHelperExtension.php';
require _FULL_APP_PATH_.'libraries'._DS_.'Hash.php';

$settings = require _FULL_APP_PATH_.'protected'._DS_.'settings.php';
session_start();
$app = new \Slim\App($settings);

require _FULL_APP_PATH_.'protected'._DS_.'dependencies.php';

require _FULL_APP_PATH_.'protected'._DS_.'common-data'._DS_.'common-data-functions.php';
require _FULL_APP_PATH_.'protected'._DS_.'login'._DS_.'login-functions.php';
require _FULL_APP_PATH_.'protected'._DS_.'dashboard'._DS_.'dashboard-functions.php';
require _FULL_APP_PATH_.'protected'._DS_.'membership'._DS_.'membership-functions.php';
require _FULL_APP_PATH_.'protected'._DS_.'adm'._DS_.'users'._DS_.'users-functions.php';

require _FULL_APP_PATH_.'protected'._DS_.'middlewares.php';

$app->run();

May i get your .htaccess configuration? and other configuration ? that work without virtual host.

Thank You :)

I only have 1 .htaccess and it is identical to the 2nd one you posted above. In your example you have your front controller (index.php) 2 subdirectories down. I have only tested with mine 1 subdirectory down. Let me test with your setup and see what results I get.

Why put it in a sub directory at all? just alias it. i have 3 slim apps running in the root directory along with an angularjs front end that just loads from an html index file, all sharing a backend codebase off in another directory. you should be able to do this same thing in apache i'm sure.

example:

location ~ ^/api {
    try_files $request_uri $request_uri/ /api.php?$query_string;
}

location ~ ^/admin {
    try_files $request_uri $request_uri/ /admin.php?$query_string;
}

location ~ ^/debug {
    try_files $request_uri $request_uri/ /debug.php?$query_string;
}

location / {
    try_files $uri /index.html;
}

so in each of api.php,admin.php, and debug.php i have a group wrapping all the routes like so

$app->group('/api',function() use($app){
... routes here
});

Why over complicate things by using an actual directory? i don't see the advantage of that at all.

aahhh thank you very much @r3wt and @silentworks , my problem solved!
it's because Garret advises me to not over complicate things.. hahahaha thx by the way :)

Now my ap structure looks like below :

C:\xampp\htdocs
---- slim3-app
-------- libraries
-------- protected
-------- public
------------ css
------------ js
------------ images
-------- vendor
-------- .htaccess
-------- index.php

The source of the problem is putting index.php and .htaccess in slim3-app/public aahh bad..bad..
soo.. i remove index.php and .htaccess in slim3-app/public and then use only one index.php and .htaccess in slim3-app/

my .htaccess

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]

i'm so sorryy.. I've been prejudiced that this is Slim 3 router bugs.

Thank you very much guys :)

Happy to hear you got this resolved. Thanks @r3wt for helping out.

@okaprinarjaya, Yep, it works for me and I fix it like you said. Thanks!

@okaprinarjaya, it works for me Thanks!

@okaprinarjaya Your solution worked for me on Bitnami Mamp.

I have a very simple fix for you to get Slim 3 running in a subdirectory:

I will show you how to fix the slim/slim-skeleton app:

  1. Create a new project (or take your existing project)
    cd c:\xampp\htdocs\
    composer create-project slim/slim-skeleton slim3-app

  2. Create a new file: c:\xampp\htdocs\slim3-app\.htaccess

Content of .htaccess

RewriteEngine on
RewriteRule ^$ public/ [L]
RewriteRule (.*) public/$1 [L]
  1. Fixing the script path

Open: c:\xampp\htdocs\slim3-app\src\dependencies.php

Add this lines to fix it:

<?php

// ....

$container['environment'] = function () {
    // Fix the Slim 3 subdirectory issue (#1529)
    // This fix makes it possible to run the app from localhost/slim3-app
    $scriptName = $_SERVER['SCRIPT_NAME'];
    $_SERVER['REAL_SCRIPT_NAME'] = $scriptName;
    $_SERVER['SCRIPT_NAME'] = dirname(dirname($scriptName)) . '/' . basename($scriptName);
    return new Slim\Http\Environment($_SERVER);
};

// ...

Now you can open the app via: http://localhost/slim3-app.

Thanks very much, this solved it for me too. I am operating on a test server with lots of different projects under the document root. So my public url URL is like http://server/appName/public and I wanted everything to appear as if it is coming from http://server/appName/

I wanted the public directory to have nothing but a simple index.php file and other assets. and this solves it.

Because the slim will set main base dir start from where you run the slim app.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

feryardiant picture feryardiant  路  20Comments

Sam-Burns picture Sam-Burns  路  53Comments

l0gicgate picture l0gicgate  路  83Comments

konskript picture konskript  路  62Comments

zyx-rd picture zyx-rd  路  19Comments