Slim: Routes in subfolder

Created on 19 Aug 2017  路  18Comments  路  Source: slimphp/Slim

TL/DR

Actual behavior: to set a route, I need to specify the full request uri.
Expected behavior: to set a route, I want to specify only the path that comes after my aplication entrypoint.

The full issue

I have the follow folder structure:

  • root

    • .git

    • .idea

    • logs

    • src

    • App

    • Domain

    • Infra

    • public



      • config


      • Controller


      • public


      • view


      • .htaccess


      • index.php (application entrypoint)



    • vendor

    • .htaccess

.htaccess

When I try to rewrite the URL to config application entrypoint, I use the follow:

Options +FollowSymLinks -MultiViews

# DocumentRoot /src/public

<IfModule mod_rewrite.c>

    RewriteEngine on
    # RewriteBase /
    # RewriteCond $1 !^(index\.php|resources|robots\.txt)
    # RewriteCond %{REQUEST_FILENAME} !-f
    # RewriteCond %{REQUEST_FILENAME} !-d
    #
    # # RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
    # # RewriteRule ^(.*)$ /src/public/index.php/$1 [L,QSA]
    # # RewriteCond %{REQUEST_URI} !src/public/
    # # RewriteRule (.*) /src/public/$1 [L]

    # RewriteRule ^(.*)$ index.php/$1 [L,QSA]

    # RewriteCond %{HTTP_HOST} ^127.0.0.1$ [NC,OR]
    # RewriteCond %{HTTP_HOST} ^www.127.0.0.1$
    RewriteCond %{REQUEST_URI} !src/public/
    RewriteRule (.*) src/public/index.php/$1 [L]

</IfModule>

The comments in this .htaccess are things I already tryied.

src/public/index.php

The issue is: as long as Slim uses $_SERVER['REQUEST_URI'] to match the routes, I'm unable to use routes like $app->get('/auth', ...) and I'm forced to write all my path that comes before my entrypoint.

This is very blocking, because if I move my application to another folder, I lose every route.

To workaround this issue I replaced the request URI in src/public/index.php as above:

<?php

/*
 * Slim issue that routes based on domain instead of entrypoint.
 */
$_SERVER['REQUEST_URI'] = $_SERVER['PATH_INFO']; // gambi, arranjo tecnico

This way I'm able to route things relative to my entrypoint (index.php/...).

Slim 3 question

Most helpful comment

The following steps are necessary for your Slim application to work within subdirectories.

Directory structure:

  • public/ Web server files (the DocumentRoot on your prod server)

    • .htaccess Apache redirect rules for the front controller

    • index.php The front controller

  • .htaccess Internal redirect to the public/ directory

The content of the file: .htaccess:

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

The content of the file: public/.htaccess:

# Redirect to front controller
RewriteEngine On
# RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L] 

Add this container entry to the file: dependencies.php:

// Activating routes in a subfolder
$container['environment'] = function () {
    $scriptName = $_SERVER['SCRIPT_NAME'];
    $_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.

Edit: I copied the content from my StackOverflow answer

All 18 comments

It seems to be more of a problem with your .htaccess than a problem with Slim routes.
I think you should set the RewriteBase directive in your .htaccess, something like this:

RewriteEngine On

RewriteBase /src/public/

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

Even with this .htaccess code, it's still not working. When I try domain/subfolder/auth I got:

Not Found

The requested URL /src/public/index.php was not found on this server.

Can you just use the default Slim provided HTACCESS to see if that works ;)

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

:)

Doesn't even gets close to work. 馃槄馃槶

... weird cause it works for me.

Did you set the VHOST webroot to the public directory?

I believe that this should work:

RewriteEngine on
RewriteBase /src/public/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(/.*)?$ index.php$1 [QSA,L]

But it doesn't.

File structure (from root):
image

Browser:
image

I'm currently using EasyPHP to simulate a production environment.

@geggleto unfortunately I'm a newbie to VHOSTs, so as you can suppose, I didn't even configure one.

This is not a Slim issue but general configuration issue. If Apache document root is set to <path>/src/public/ then use RewriteBase /. If Apache document root is <path> the use RewriteBase /src/public/.

Ie. check what the document root actually is: var_dump($_SERVER['DOCUMENT_ROOT']);.

That said if document root is <path>/src/public/ ie the folder where main index.php is located the default .htaccess from documentation should work ok, no need to set RewriteBase.

In this point of view, this is a problem with my config, but in the point of view of the approach I tryied, if Slim just make use of PATH_INFO instead of REQUEST_URI, all the problem would be solved.

I'll keep trying to adapt my approach to the approach that you'r tellin' me to use, but I gotta ask, why Slim doesn't make use of PATH_INFO?

TA. ASAP I'll make tests with my server document root.

because life does not revolve around apache ;)

PATH_INFO is related to the Apache Web Server serving PHP pages

We support any web-server and thus cannot rely on solely PATH_INFO.

I was also having this issue, but have not been able to fix it other than to create extra routes in my application, pointing to the same code as other routes. Not the best solution perhaps, but it works. There seems to be no way to change REQUEST_URI without, well, changing the request URI (and I don't want it to change, from the user's perspective).

@samwilson I find it very odd that you are having this problem. I have not had any problem with Routing and I use it extensively on dozens of projects.

@geggleto it's because I was trying to rewrite another URL, but not change it, and so Slim was only seeing the original, non-routed REQUEST_URI.

The following steps are necessary for your Slim application to work within subdirectories.

Directory structure:

  • public/ Web server files (the DocumentRoot on your prod server)

    • .htaccess Apache redirect rules for the front controller

    • index.php The front controller

  • .htaccess Internal redirect to the public/ directory

The content of the file: .htaccess:

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

The content of the file: public/.htaccess:

# Redirect to front controller
RewriteEngine On
# RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L] 

Add this container entry to the file: dependencies.php:

// Activating routes in a subfolder
$container['environment'] = function () {
    $scriptName = $_SERVER['SCRIPT_NAME'];
    $_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.

Edit: I copied the content from my StackOverflow answer

Thank you @odan. Your solution led me to a more general one, that works for different levels of nesting.

I ended up with this in the bootstrap sequence:

 //Create the App with settings
 $app = new \Slim\App(['settings' => settings()]);
 //correct routes
 $_SERVER['SCRIPT_NAME'] = $app->getContainer()->get('settings')['scriptURI'];

The Setting['scriptURI'] is the actual URI of the base script index.php:
http://localhost/app1/index.php ---> /app1/index.php
http://localhost/index.php ---> /index.php

Going to close this as this is Server configuration and out of scope for the repo. If further assistance is required try our slack or discourse community. Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

cacharrin picture cacharrin  路  23Comments

Sam-Burns picture Sam-Burns  路  53Comments

konskript picture konskript  路  62Comments

codeguy picture codeguy  路  43Comments

akrabat picture akrabat  路  43Comments