2

As most frameworks out there, Silex depends on rewrite rules to handle pretty urls. The default .htaccess recommended for use with this framework is

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]

Which is straightforward and works just fine. But if I also want to rewrite the request uri to always include a trailing slash I can't get it to work. I tried using the following rules before.

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^(.*)/$
RewriteRule . %{REQUEST_URI}/ [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]

To debug this, I've tried forcing a redirect using the [R] flag and I can see that it evaluates correctly but both rules together don't do the trick as the resulting request uri still remains without a trailing slash.

To sum up: example.com/foo should redirect to example.com/foo/ and in the end handled by index.php. example.com/foo/ should be handled by index.php without modifications.

I am not an expert in mod_rewrite but I've spent a signifficant time reading through the docs here and I have a gut feeling that this should be possible to solve this way.

Thanks in advance, Alex

1
  • Other than requiring the R flag in your trailing slash rule, these work fine for me in a blank htaccess file and a default apache 2.2 install.
    – Jon Lin
    Dec 25, 2012 at 0:53

1 Answer 1

1

It turns out apache and mod_rewrite are actually working the way they should given the setup shown in the question. The php framework was not making use of the right url.

When using php with apache, apache creates several server variables (namely the $_SERVER global).

So given the above rewrite rules, when a user navigates to example.com/resource apache would first rewrite to example.com/resource/ and subsequently handing everything to index.php to handle. What was not so obvious was that the $_SERVER['REQUEST_URI'] variable was not changed, rather the $_SERVER['REDIRECT_URL'] was being set with the new rewritten uri.

So the issue of not redirecting was actually the framework that never used the new global introduced by apache. To make use of this global variable, extend the existing Silex/Application.php and overwrite its run() method like so:

class Application extends Silex\Application
{
    public function run(Request $request = null)
    {
        if (null === $request) {
            if (isset($_SERVER['REDIRECT_URL'])) {
                $_SERVER['REQUEST_URI'] = $_SERVER['REDIRECT_URL'];
            }
            $request = Request::createFromGlobals();
        }
        $response = $this->handle($request);
        $response->send();
        $this->terminate($request, $response);
    }

}

Hope this helps!

Alex

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .