Martin AJ
Martin AJ

Reputation: 6707

How to make public folder as root in Laravel?

I am using the Laravel framework to create a web application. Laravel applications are accessed from index.php in the app's public directory.

The homepage route is defined as:

Route::get('/', 'HomeController@index');

But I can only access this from the URL https://example.com/public.

How can I make the /public folder as root?


Curently I've found a workaround. I can create an index.php on the root and write a redirect code to /public folder. So when user enters http://example.com/, it will be redirected to http://example.com/public automatically. But still that's ugly. I don't like to see /public in the URL. Any suggestion?

Upvotes: 18

Views: 44117

Answers (5)

Shyam Yadav
Shyam Yadav

Reputation: 51

you can use RewriteRule ^public(/.*)?$ / [R=301,L] when URL hit domain/public then redirect 301

<IfModule mod_rewrite.c>
    RewriteEngine On

    # Redirect requests to /public to the root URL
    RewriteRule ^public(/.*)?$ / [R=301,L]

    # Rewrite all other requests to the public folder
    RewriteCond %{REQUEST_URI} !^/public/
    RewriteRule ^(.*)$ public/$1 [L]
</IfModule>

Upvotes: 0

rozsazoltan
rozsazoltan

Reputation: 9625

Domain's document root

The domain name should point to the /public folder as if it were your public_html folder.

Whenever a request is made to this domain, the index.php should be executed

You need to place an .htaccess file in the /public folder that contains the lines you mentioned, especially these:

# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]

# Send Requests To Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]

Return the appropriate content due to Laravel routing

This way, every URL called under a domain name will start from your /public/index.php, which builds up your Laravel app. Eventually, it will either run the appropriate route defined in the /routes or return a 404 blank page if no matching route is found.

Conclusion

The /public appears in the URL if your domain name points to your-project instead of your-project/public. Therefore, you can access your starting index.php with https://example.com/public/index.php.

# normal directory tree
server
├── your-project
│   ├── app
│   ├── routes
│   ├── public        <--- domain root
│   │   ├── index.php
│   │   └── .htaccess
│   ├── ...

If the root of your domain points to the /your-project/public folder and you can still access its content using the /public address, then either you have incorrectly set up the Route in the /routes/web.php file (perhaps created a group named "public" or added the /public URL part to every route), or your domain is pointing to the /your-project folder incorrectly.

Extra: if can't change domain's root

It is possible that you do not have control over which directory the domain name points to, for example, it may be fixed to the "public_html" directory. That's no problem.

Place the contents of the /your-project/public directory here. Then, at the same level as public_html, place the your-project directory. After that, modify all references in /your-project/public/index.php that point to the directory one level above using ../. Instead, replace it with ../your-project.

Example:

# changed directory tree (when has fixed domain's root)
server
├── your-project
│   ├── app
│   ├── routes
│   └── ...
├── public_html     <--- domain root
│   ├── index.php
│   └── .htaccess
<?php
// your-project/public/index.php --> public_html/index.php

use Illuminate\Contracts\Http\Kernel;
use Illuminate\Http\Request;

define('LARAVEL_START', microtime(true));

// ../your-project/ instead of ../
if (file_exists($maintenance = __DIR__.'/../your-project/storage/framework/maintenance.php')) {
    require $maintenance;
}

// ../your-project/ instead of ../
require __DIR__.'/../your-project/vendor/autoload.php';

// ../your-project/ instead of ../
$app = require_once __DIR__.'/../your-project/bootstrap/app.php';

$kernel = $app->make(Kernel::class);

$response = $kernel->handle(
    $request = Request::capture()
)->send();

$kernel->terminate($request, $response);

Upvotes: 1

DragonFire
DragonFire

Reputation: 4102

For running Apache on Ubuntu, do the following. This assumes you have Composer and PHP already installed.

# create your web directory
sudo mkdir -p /var/www/example.com
# install laravel
cd /var/www/example.com
composer create-project laravel/laravel example-app
# proper ownership
sudo chown -R www-data:www-data /var/www/example.com
# create a configuration
sudo nano /etc/apache2/sites-available/example.com.conf

Then in the file paste

<VirtualHost *:443>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/example.com/public
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    # SSL configuration, etc.
</VirtualHost>

Then run

# enable your site
sudo a2ensite <your domain>
# disable the default site
sudo a2dissite 000-default
# restart the web server
sudo systemctl reload apache2

Upvotes: 2

Alexey Mezenin
Alexey Mezenin

Reputation: 163978

Do not modify any Laravel files. Instead configure your web server (Apache or Nginx) to point to the Laravel project's public directory.

For Apache you can use these directives:

DocumentRoot "/path_to_laravel_project/public"
<Directory "/path_to_laravel_project/public">

For nginx, you should change this line:

root /path_to_laravel_project/public;

Having your document root as /path_to_laravel_project/ alone will create serious security risks, potentially opening your entire app configuration to the internet.

Upvotes: 11

Piyush
Piyush

Reputation: 65

Step 1: Put your /public/index.php and /public/htaccess file to your root directory as /index.php and /htaccess .
Step 2: Now Make changes in your index.php

require __DIR__.'/../bootstrap/autoload.php'; //OLD code
$app = require_once __DIR__.'/../bootstrap/app.php';

to

 require __DIR__.'./bootstrap/autoload.php'; //NEW code
 $app = require_once __DIR__.'./bootstrap/app.php';

Upvotes: 2

Related Questions