I'm trying to set up a Symfony 3.4 project on an Apache (2.4.25) server. However, I'm facing issues with the rooting.
The application works smoothly with the built-in server (all routes). However, on Apache server, I'm unable to access the login page. The /login
path is automatically change to web/login
and result in:
No route found for "GET /web/login/"
Since the application (and the routing) is working with the built-in server, I suspect an issue in the apache configuration. In the built-in server, the /login
isn't rewrite.
Note:
Here the Apache files:
.htaccess
in the web
folder:
# Use the front controller as index file. It serves as 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
# startpage (path "/") because otherwise Apache will apply the rewritting rules
# to each configured DirectoryIndex file (e.g. index.php, index.html, index.pl).
DirectoryIndex app.php
<IfModule mod_rewrite.c>
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 ^app\.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 ^(.*)$ app.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}app.php [L]
</IfModule>
<IfModule !mod_rewrite.c>
<IfModule mod_alias.c>
# When mod_rewrite is not available, we instruct a temporary redirect of
# the startpage to the front controller explicitly so that the website
# and the generated links can still be used.
RedirectMatch 302 ^/$ /app.php/
</IfModule>
</IfModule>
site.conf
:
<VirtualHost *:80>
ServerName sub.domain.fr
DocumentRoot /var/www/symfony/web
<Directory /var/www/symfony/web>
AllowOverride All
Require all granted
Allow from All
</Directory>
ErrorLog /var/log/apache2/project_error.log
CustomLog /var/log/apache2/project_access.log combined
</VirtualHost>
<VirtualHost *:80>
ServerName domain.fr
ServerAlias www.domain.fr
DocumentRoot /var/www/drupal-site
<Directory /var/www/drupal-site>
AllowOverride all
Order allow,deny
allow from all
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Symfony files:
app/config/routing.yml
carte:
resource: "@CarteBundle/Controller/"
type: annotation
reservation:
# loads routes from the PHP annotations of the controllers
resource: '@ReservationBundle/Controller/'
type: annotation
app:
resource: '@AppBundle/Controller/'
type: annotation
user_bundle:
resource: "@AppBundle/Resources/config/routing.yml"
admin:
resource: '@SonataAdminBundle/Resources/config/routing/sonata_admin.xml'
prefix: /admin
_sonata_admin:
resource: .
type: sonata_admin
prefix: /admin
homepage:
path: /
defaults: { _controller: AppBundle:Default:index }
# Lexik Paybox Bundle
lexik_paybox:
resource: '@LexikPayboxBundle/Resources/config/routing.yml'
lexik_paybox_sample_return:
path: /payment/return/{status}
defaults: { _controller: LexikPayboxBundle:Sample:return, status: error }
requirements:
status: success|canceled|denied
src/AppBundle/Resources/config/routing.yml
:
fos_user_security:
resource: "@FOSUserBundle/Resources/config/routing/security.xml"
fos_user_profile:
resource: "@FOSUserBundle/Resources/config/routing/profile.xml"
prefix: /profile
fos_user_register:
resource: "@FOSUserBundle/Resources/config/routing/registration.xml"
prefix: /register
fos_user_resetting:
resource: "@FOSUserBundle/Resources/config/routing/resetting.xml"
prefix: /resetting
fos_user_change_password:
resource: "@FOSUserBundle/Resources/config/routing/change_password.xml"
prefix: /profile
sonata_admin_dashboard:
path: /admin/dashboard
defaults: { _controller: "AppBundle:Admin:index" }
fos_user:
resource: "@FOSUserBundle/Resources/config/routing/all.xml
app/config/security.yml
security:
encoders:
FOS\UserBundle\Model\UserInterface: bcrypt
role_hierarchy:
ROLE_USER: [ROLE_CLIENT]
ROLE_CONTROLEUR: [ROLE_CLIENT, ROLE_CONTROLEUR]
ROLE_ADMIN: [ROLE_CLIENT, ROLE_CONTROLEUR, ROLE_ADMIN]
ROLE_SUPER_ADMIN: [ROLE_CLIENT, ROLE_CONTROLEUR, ROLE_ADMIN, ROLE_SUPER_ADMIN]
providers:
in_memory:
memory: ~
fos_userbundle:
id: fos_user.user_provider.username
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
provider: fos_userbundle
guard:
authenticators:
- app.security.login_form_authenticator
logout: true
anonymous: true
api_password_reset:
pattern: ^/password/reset
anonymous: true
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/reservation/+\d, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/reservation/edition/+\d, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/reservation/from_code, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/reservation/creation, role: ROLE_CLIENT }
- { path: ^/pecheur, role: ROLE_CLIENT }
- { path: ^/controleur, role: ROLE_CONTROLEUR }
- { path: ^/admin, role: [ROLE_ADMIN] }
Output from php bin/console debug:router fos_user_security_login
:
+--------------+-----------------------------------------------------------+
| Property | Value |
+--------------+-----------------------------------------------------------+
| Route Name | fos_user_security_login |
| Path | /login |
| Path Regex | #^/login$#s |
| Host | ANY |
| Host Regex | |
| Scheme | ANY |
| Method | GET|POST |
| Requirements | NO CUSTOM |
| Class | Symfony\Component\Routing\Route |
| Defaults | _controller: fos_user.security.controller:loginAction |
| Options | compiler_class: Symfony\Component\Routing\RouteCompiler |
| Callable | FOS\UserBundle\Controller\SecurityController::loginAction |
+--------------+-----------------------------------------------------------+
Stack Traces
Symfony\Component\HttpKernel\Exception\NotFoundHttpException:
No route found for "GET /web/login/"
at vendor/symfony/symfony/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php:128
at Symfony\Component\HttpKernel\EventListener\RouterListener->onKernelRequest(object(GetResponseEvent), 'kernel.request', object(TraceableEventDispatcher))
at call_user_func(array(object(RouterListener), 'onKernelRequest'), object(GetResponseEvent), 'kernel.request', object(TraceableEventDispatcher))
(vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php:104)
at Symfony\Component\EventDispatcher\Debug\WrappedListener->__invoke(object(GetResponseEvent), 'kernel.request', object(ContainerAwareEventDispatcher))
at call_user_func(object(WrappedListener), object(GetResponseEvent), 'kernel.request', object(ContainerAwareEventDispatcher))
(vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/EventDispatcher.php:212)
at Symfony\Component\EventDispatcher\EventDispatcher->doDispatch(array(object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener), object(WrappedListener)), 'kernel.request', object(GetResponseEvent))
(vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/EventDispatcher.php:44)
at Symfony\Component\EventDispatcher\EventDispatcher->dispatch('kernel.request', object(GetResponseEvent))
(vendor/symfony/symfony/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php:139)
at Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher->dispatch('kernel.request', object(GetResponseEvent))
(vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php:127)
at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1)
(vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php:68)
at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
(vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php:169)
at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
(web/app.php:17)
Maybe that might help other people one day. I solved it after trying to debug with a test function:
/**
* @Route("/test", name="test")
* @return Response
*/
public function testAction(){
return $this->redirect($this->generateUrl('fos_user_security_login'));
}
Then I went on "/test" page from the web browser and the login
appears !
I suspect this was a problem of cache or something like this...