Yii 2.0: How to hide /frontend/web in url addresses on apache

18 followers

There is an issue on Yii2 to redirecting / urls to /frontend/web.
In other words we need a way to hidden /frontend/web from addresses.
We will do this without changing Apache configuration and creating virtual host or setting document root (It's good for share hostings that we have not access to apache.conf)

Let's do it:

1- Create .htaccess file on the root directory with this content

Options -Indexes

<IfModule mod_rewrite.c> 
  RewriteEngine on

  RewriteCond %{REQUEST_URI} !^public
  RewriteRule ^(.*)$ frontend/web/$1 [L] 
</IfModule>

# Deny accessing below extensions
<Files ~ "(.json|.lock|.git)">
Order allow,deny
Deny from all
</Files>

# Deny accessing dot files
RewriteRule (^\.|/\.) - [F]

2- Create .htaccess file in frontend/web with the below contents

RewriteEngine on

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d 

RewriteRule . index.php

3- Now, we should play a little with frontend config of framework
You must open the frontend/config/main.php file and set $baseUrl for \yii\web\Request and \yii\web\urlManager.
$baseUrl is the url your application point to. if you host your application in the root directory of www you may set the $baseUrl to '/'

For another example if you are developing a blog system and your application hosted in www/blog you must set the baseUrl to '/blog'

<?php
$params = array_merge(
    require(__DIR__ . '/../../common/config/params.php'),
    require(__DIR__ . '/../../common/config/params-local.php'),
    require(__DIR__ . '/params.php'),
    require(__DIR__ . '/params-local.php')
);
 
 
return [
    'id' => 'app-frontend',
    'basePath' => dirname(__DIR__),
    'bootstrap' => ['log'],
    'controllerNamespace' => 'frontend\controllers',
 
    'components' => [
 
        'request' => [
            'baseUrl' => '/',
        ],
 
        'user' => [
            'identityClass' => 'common\models\User',
            'enableAutoLogin' => true,
        ],
 
        'log' => [
            'traceLevel' => YII_DEBUG ? 3 : 0,
            'targets' => [
                [
                    'class' => 'yii\log\FileTarget',
                    'levels' => ['error', 'warning'],
                ],
            ],
        ],
 
        'errorHandler' => [
            'errorAction' => 'site/error',
        ],
 
        'urlManager' => [
            'baseUrl' => '/',
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'rules' => []
        ]
    ],
    'params' => $params,
];

Soft Way

If you not sure where your application will host, you must do it in pragmatically way. for this purpose we change the config file as below

<?php
$params = array_merge(
    require(__DIR__ . '/../../common/config/params.php'),
    require(__DIR__ . '/../../common/config/params-local.php'),
    require(__DIR__ . '/params.php'),
    require(__DIR__ . '/params-local.php')
);
 
use \yii\web\Request;
$baseUrl = str_replace('/frontend/web', '', (new Request)->getBaseUrl());
 
return [
    'id' => 'app-frontend',
    'basePath' => dirname(__DIR__),
    'bootstrap' => ['log'],
    'controllerNamespace' => 'frontend\controllers',
 
    'components' => [
 
        'request' => [
            'baseUrl' => $baseUrl,
        ],
 
        'user' => [
            'identityClass' => 'common\models\User',
            'enableAutoLogin' => true,
        ],
 
        'log' => [
            'traceLevel' => YII_DEBUG ? 3 : 0,
            'targets' => [
                [
                    'class' => 'yii\log\FileTarget',
                    'levels' => ['error', 'warning'],
                ],
            ],
        ],
 
        'errorHandler' => [
            'errorAction' => 'site/error',
        ],
 
        'urlManager' => [
            'baseUrl' => $baseUrl,
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'rules' => []
        ]
    ],
    'params' => $params,
];

As you see above we use \yii\web\Request to find $baseUrl of application. but because the returned $baseUrl contains /frontend/web we remove it

use \yii\web\Request;
$baseUrl = str_replace('/frontend/web', '', (new Request)->getBaseUrl());

enjoy !

Total 15 comments

#20121 report it
Gregory at 2017/08/27 05:31am
Clean the URL up after redirecting on shared host.

Thanks!

The soft version was the simplest solution after redirecting using .htaccess.
It's nice not to have to move directories and file around.

#19880 report it
jerome nicholas at 2016/06/15 08:31am
common folder library reference error AppAsset.php

i got an error accessing libraries in the common folder

so i had to put the lib folder in frontend and backend..

cool solution

#19479 report it
Amjad Khan at 2015/07/21 11:39pm
Page not found error while getting backend

i implement this code on my localhost. it works fine on frontend, no problem in debug toolbar as well, my project name is yii2test but when i go to

localhost/yii2test/backend

it shows page not found error Please help

#19279 report it
realtebo at 2015/05/08 04:58am
Could you extend this tutorial to enable /something to point to backend?

In this situation, we've also backend/web to use.

Can you please extend this example to be abale to use domain.tld/something to open /backend/www/index.php ?

Thank you in advance

#18895 report it
raminious at 2015/01/31 03:29pm
Re: Thanks, but I've this problem

I didn't see any problem with Debug toolbar and I need more info to solve your problem

Thank You!

#18887 report it
realtebo at 2015/01/29 09:23am
Thanks, but I've this problem

At the end someone explaing us exactly how to make usable shared hosting and pretty url at same time !!!!

you're my hero !

COMMENT EDITED: no problem with debug toolbar

#18782 report it
Chrles at 2015/01/06 06:07am
Images folder at root

This works great. Thanks for this article. But images won't display if the "Images" folder is located at webroot in order to be shared by both Frontend and Backend.

#18442 report it
jtag05 at 2014/10/29 04:13pm
Re: vendor, common, etc folders

I'm pretty sure that the following prevents all requests that aren't directed at the public directory to be routed to /frontend/web/

RewriteCond %{REQUEST_URI} !^public
RewriteRule ^(.*)$ frontend/web/$1 [L] 
#18437 report it
taskas at 2014/10/29 06:09am
vendor, common, etc folders

As I understand, with this method you should also keep in mind, that vendor/, common/ and other folders are at root level, that means it would be possible to open let's say http://your.domain/vendor/bin/yii file. Probably should put a lot of restrictions in .htaccess file. EDIT: I'm sorry, i was wrong. jtag05 is right.

#18332 report it
Rohit Suthar at 2014/10/17 07:45am
Thanks for sharing

It's a nice article.... thanks for the sharing this :)..

#18314 report it
raminious at 2014/10/14 09:12am
Reply To: And for backend?

hiding /backend/web/index.php is same as the frontend. but you could play with root .htaccess file and add new rules and condition to .htaccess file Anymore I think redirecting /backend/web is less important than /frontend and not include this section in my article.

#18305 report it
raminious at 2014/10/14 09:08am
Reply To: Create VirtualHost

If you have access to Apahce configurations, it's better to use Virtual Host instead my solution. but if you are working on shared hostings, or assume that the end user of your application host your application on shared hostings, its better for you to use the demonstrated solution.

#18302 report it
fahadakram at 2014/10/14 02:17am
Create VirtualHost

is it not better to create its virtual host , instead of all this code ?

#18298 report it
mimo at 2014/10/13 09:42am
Thank you

I was really looking exactly for this. Best solution (in my case) I've seen so far. Thank you :)

#18264 report it
Mojtaba Rahbari at 2014/10/08 06:59am
And for backend?

I'm going to hide frontend/www and change backend/www to something else, eg. http://domain.com/admin
Your solution is fine to hide frontend/www.
Just let me know what did you do for backend?

Leave a comment

Please to leave your comment.

Write new article