Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@alch
Last active March 19, 2024 23:38
Show Gist options
  • Star 26 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save alch/7766993 to your computer and use it in GitHub Desktop.
Save alch/7766993 to your computer and use it in GitHub Desktop.
Symfony full .htaccess file
# For a symfony application to work properly, you MUST store this .htaccess in
# the same directory as your front controller, index.php, in a standard symfony
# web application is under the "public" project subdirectory.
# Use the front controller as index file.
DirectoryIndex index.php
# Uncomment the following line if you install assets as symlinks or if you
# experience problems related to symlinks when compiling LESS/Sass/CoffeScript.
# Options +FollowSymlinks
# Disabling MultiViews prevents unwanted negotiation, e.g. "/index" should not resolve
# to the front controller "/index.php" but be rewritten to "/index.php/index".
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine On
# This RewriteRule is used to dynamically discover the RewriteBase path.
# See https://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewriterule
# Here we will compare the stripped per-dir path *relative to the filesystem
# path where the .htaccess file is read from* with the URI of the request.
#
# If a match is found, the prefix path is stored into an ENV var that is later
# used to properly prefix the URI of the front controller index.php.
# This is what makes it possible to host a Symfony application under a subpath,
# such as example.com/subpath
# The convoluted rewrite condition means:
# 1. Match all current URI in the RewriteRule and backreference it using $0
# 2. Strip the request uri the per-dir path and use ir as REQUEST_URI.
# This is documented in https://bit.ly/3zDm3SI ("What is matched?")
# 3. Evaluate the RewriteCond, assuming your DocumentRoot is /var/www/html,
# this .htaccess is in the /var/www/html/public dir and your request URI
# is /public/hello/world:
# * strip per-dir prefix: /var/www/html/public/hello/world -> hello/world
# * applying pattern '.*' to uri 'hello/world'
# * RewriteCond: input='/public/hello/world::hello/world' pattern='^(/.+)/(.*)::\\2$' => matched
# 4. Execute the RewriteRule:
# * The %1 in the RewriteRule flag E=BASE:%1 refers to the first group captured in the RewriteCond ^(/.+)/(.*)
# * setting env variable 'BASE' to '/public'
RewriteCond %{REQUEST_URI}::$0 ^(/.+)/(.*)::\2$
RewriteRule .* - [E=BASE:%1]
# Sets the HTTP_AUTHORIZATION header removed by Apache
RewriteCond %{HTTP:Authorization} .+
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0]
# Removes the /index.php/ part from a URL, if present
RewriteCond %{ENV:REDIRECT_STATUS} =""
RewriteRule ^index\.php(?:/(.*)|$) %{ENV:BASE}/$1 [R=301,L]
# If the requested filename exists, simply serve it.
# Otherwise rewrite all other queries to the front controller.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ %{ENV:BASE}/index.php [L]
</IfModule>
<IfModule !mod_rewrite.c>
<IfModule mod_alias.c>
# When mod_rewrite is not available, we instruct a temporary redirect
# to the front controller explicitly so that the website
RedirectMatch 307 ^/$ /index.php/
</IfModule>
</IfModule>
Copy link

ghost commented Mar 11, 2019

Works, except i had to rename app.php to index.php.

Thanks!

@mitchobrian
Copy link

mitchobrian commented May 5, 2020

for symfony 5* it's like that:

RewriteEngine On

# Redirect to URI without front controller to prevent duplicate content
# (with and without `/app.php`). Only do this redirect on the initial
# rewrite by Apache and not on subsequent cycles. Otherwise we would get an
# endless redirect loop (request -> rewrite to front controller ->
# redirect -> request -> ...).
# So in case you get a "too many redirects" error or you always get redirected
# to the startpage because your Apache does not expose the REDIRECT_STATUS
# environment variable, you have 2 choices:
# - disable this feature by commenting the following 2 lines or
# - use Apache >= 2.3.9 and replace all L flags by END flags and remove the
#   following RewriteCond (best solution)
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^index\.php(/(.*)|$) %{CONTEXT_PREFIX}/$2 [R=301,L]

# If the requested filename exists, simply serve it.
# We only want to let Apache serve files and not directories.
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .? - [L]

# cache-bust assets url rewrite
# Example format: /cpv-10/js/test123.js -> /js/test123.js
# This allows us to change the asset version and "bust" intermediate caches (like varnish)
# See http://symfony.com/doc/current/reference/configuration/framework.html#ref-framework-assets-version
# See http://symfony.com/doc/current/reference/configuration/framework.html#assets-version-format
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^cpv-\d+\/(.+)$ $1 [L]

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

# The following rewrites all other queries to the front controller. The
# condition ensures that if you are using Apache aliases to do mass virtual
# hosting, the base path will be prepended to allow proper resolution of the
# app.php file; it will work in non-aliased environments as well, providing
# a safe, one-size fits all solution.
RewriteCond %{REQUEST_URI}::$1 ^(/.+)(.+)::\2$
RewriteRule ^(.*) - [E=BASE:%1]
RewriteRule .? %{ENV:BASE}index.php [L]

@Guzmicz
Copy link

Guzmicz commented Jun 9, 2020

Solution for Symfony 5 is not working. Can you help me?

@mitchobrian
Copy link

How?

@Guzmicz
Copy link

Guzmicz commented Jun 9, 2020

Well, I'm not sure if I have to change something in this file. I put it into my root project folder but index.php is in the public folder. So I still have to go on localhost/my-project/public to get on my website.

@mitchobrian
Copy link

Sure, you need to move the .htaccess also in /public and change the root for your domain to the /public folder.

@dkachuk
Copy link

dkachuk commented Feb 9, 2021

Hola a todos!
Yo he utilizado esta configuración con Apache2 sobre Windows 10 en modo local y funcionó.
Lo encontré en esta url https://ourcodeworld.com/articles/read/1103/how-to-configure-a-virtualhost-in-xampp-3-3-2-for-a-symfony-5-project

Use the front controller as index file. It serves as a fallback solution when

every other rewrite/redirect fails (e.g. in an aliased environment without

mod_rewrite). Additionally, this reduces the matching process for the

start page (path "/") because otherwise Apache will apply the rewriting rules

to each configured DirectoryIndex file (e.g. index.php, index.html, index.pl).

DirectoryIndex index.php

By default, Apache does not evaluate symbolic links if you did not enable this

feature in your server configuration. Uncomment the following line if you

install assets as symlinks or if you experience problems related to symlinks

when compiling LESS/Sass/CoffeScript assets.

Options FollowSymlinks

Disabling MultiViews prevents unwanted negotiation, e.g. "/index" should not resolve

to the front controller "/index.php" but be rewritten to "/index.php/index".

Options -MultiViews RewriteEngine On
# Determine the RewriteBase automatically and set it as environment variable.
# If you are using Apache aliases to do mass virtual hosting or installed the
# project in a subdirectory, the base path will be prepended to allow proper
# resolution of the index.php file and to redirect to the correct URI. It will
# work in environments without path prefix as well, providing a safe, one-size
# fits all solution. But as you do not need it in this case, you can comment
# the following 2 lines to eliminate the overhead.
RewriteCond %{REQUEST_URI}::$0 ^(/.+)/(.*)::\2$
RewriteRule .* - [E=BASE:%1]

# Sets the HTTP_AUTHORIZATION header removed by Apache
RewriteCond %{HTTP:Authorization} .+
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0]

# Redirect to URI without front controller to prevent duplicate content
# (with and without `/index.php`). Only do this redirect on the initial
# rewrite by Apache and not on subsequent cycles. Otherwise we would get an
# endless redirect loop (request -> rewrite to front controller ->
# redirect -> request -> ...).
# So in case you get a "too many redirects" error or you always get redirected
# to the start page because your Apache does not expose the REDIRECT_STATUS
# environment variable, you have 2 choices:
# - disable this feature by commenting the following 2 lines or
# - use Apache >= 2.3.9 and replace all L flags by END flags and remove the
#   following RewriteCond (best solution)
RewriteCond %{ENV:REDIRECT_STATUS} =""
RewriteRule ^index\.php(?:/(.*)|$) %{ENV:BASE}/$1 [R=301,L]

# If the requested filename exists, simply serve it.
# We only want to let Apache serve files and not directories.
# Rewrite all other queries to the front controller.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ %{ENV:BASE}/index.php [L]

<IfModule !mod_rewrite.c>

# When mod_rewrite is not available, we instruct a temporary redirect of
# the start page to the front controller explicitly so that the website
# and the generated links can still be used.
RedirectMatch 307 ^/$ /index.php/
# RedirectTemp cannot be used instead

@bastoune
Copy link

for symfony 5* it's like that:

RewriteEngine On

# Redirect to URI without front controller to prevent duplicate content
# (with and without `/app.php`). Only do this redirect on the initial
# rewrite by Apache and not on subsequent cycles. Otherwise we would get an
# endless redirect loop (request -> rewrite to front controller ->
# redirect -> request -> ...).
# So in case you get a "too many redirects" error or you always get redirected
# to the startpage because your Apache does not expose the REDIRECT_STATUS
# environment variable, you have 2 choices:
# - disable this feature by commenting the following 2 lines or
# - use Apache >= 2.3.9 and replace all L flags by END flags and remove the
#   following RewriteCond (best solution)
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^index\.php(/(.*)|$) %{CONTEXT_PREFIX}/$2 [R=301,L]

# If the requested filename exists, simply serve it.
# We only want to let Apache serve files and not directories.
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .? - [L]

# cache-bust assets url rewrite
# Example format: /cpv-10/js/test123.js -> /js/test123.js
# This allows us to change the asset version and "bust" intermediate caches (like varnish)
# See http://symfony.com/doc/current/reference/configuration/framework.html#ref-framework-assets-version
# See http://symfony.com/doc/current/reference/configuration/framework.html#assets-version-format
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^cpv-\d+\/(.+)$ $1 [L]

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

# The following rewrites all other queries to the front controller. The
# condition ensures that if you are using Apache aliases to do mass virtual
# hosting, the base path will be prepended to allow proper resolution of the
# app.php file; it will work in non-aliased environments as well, providing
# a safe, one-size fits all solution.
RewriteCond %{REQUEST_URI}::$1 ^(/.+)(.+)::\2$
RewriteRule ^(.*) - [E=BASE:%1]
RewriteRule .? %{ENV:BASE}index.php [L]

@mitchobrian

I tried this config but i am getting the following error:

AH00124: Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary. Use 'LogLevel debug' to get a backtrace.

@alch
Copy link
Author

alch commented Sep 1, 2021

@bastoune I updated the gist with a shorter and more updated version, based on the official Symfony Apache Pack

@belbeche
Copy link

belbeche commented Feb 3, 2023

Working on 2023 !

@Renaud-CCI
Copy link

You saved my life (or at least my brain) ! thank you !!

@danfoley
Copy link

I added the following so it will also go to any existing directory in public: (if that is what you want your application to do)

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ %{ENV:BASE}/index.php [L]

@Laure-Riglet
Copy link

Thank you, that saved precious time!

@php4fan
Copy link

php4fan commented Feb 28, 2024

Maybe a nice addition would be a redirect of http to https, perhaps commented out by default

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment