Laravel

I have seen this asked many times on the Laravel forums as well as other discussion boards. Even found myself searching and looking for a way to change the default directory structure to use it on a VPS with WHM/Cpanel.

As many of you know the default public directory is public_html when running most VPS with WHM/CPanel. Which can be a pain to deploy to under the default directory structure if you do not have access to setup symlinks or know how for that matter.

During my search I have combined suggestions I have read into one. I hope this helps some of you who have struggled with this currently and in the past.

Part 1: Moving folders to the laravel folder

First create a new folder in your root directory named ‘laravel’ (or whatever you want to call it) and move all folders and files except the ‘public’ directory into it. And rename the ‘public’ folder to ‘public_html’.

After making this change the root directory should have changed from:

-app
-bootstrap
-config
-database
-public
-resources
-routes
-storage
-tests
-vendor
.env
.env.example
.gitattributes
.gitignore
artisan
composer.json
composer.lock
package.json
phpunit.xml
readme.md
server.php
webpack.mix.js

To the new structure:

-laravel
    -app
    -bootstrap
    -config
    -database
    -resources
    -routes
    -storage
    -tests
    -vendor
    .env
    .env.example
    .gitattributes
    .gitignore
    artisan
    composer.json
    composer.lock
    package.json
    phpunit.xml
    readme.md
    server.php
    webpack.mix.js
-public_html

Part 2: Modify the public_html/index.php file and the laravel/server.php file

Open the public_html/index.php file in your favorite editor and make the following changes:

Change these lines from:

require __DIR__.'/../bootstrap/autoload.php';

$app = require_once __DIR__.'/../bootstrap/app.php';

To this:

require __DIR__.'/../laravel/bootstrap/autoload.php';

$app = require_once __DIR__.'/../laravel/bootstrap/app.php';

Now open the laravel/server.php file and make the following modifications:

Change these lines from:

if ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) {
    return false;
}

require_once __DIR__.'/public/index.php';

To this:

if ($uri !== '/' && file_exists(__DIR__.'../public_html'.$uri)) {
    return false;
}

require_once __DIR__.'../public_html/index.php';

With these changes you can now access the the index.php file and the site will work. But we still have the public_path issue which will need to be addressed.

Part 3: Fix issue with the public path

To fix the issue with calling public_path and it returning ‘laravel/public’ we need to create a new provider we can call it ConfigServiceProvider (note: This idea came from here: https://laracasts.com/discuss/channels/general-discussion/where-do-you-set-public-directory-laravel-5/replies/14105 I just changed the name from AppServiceProvider to ConfigServiceProvider).

Lets create the ConfigServiceProvider:

php artisan make:provider ConfigServiceProvider

Now open the newly created file located in app/Providers/ConfigServiceProvider and put the following content:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class ConfigServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */

    public function boot()
    {
        //
    }

    /**
     * Register the application services.
     *
     * @return void
     */

    public function register()
    {
        $this->app->bind('path.public', function() {
            return realpath('../public_html');
        });
    }
}

Now open your config/app.php file and add the newly created ConfigServiceProvider to the providers list:

App\Providers\ConfigServiceProvider::class,
Note: You should put this near the top so other parts of the system know the change was made.

Now run:

composer dump-auto

Check the public_path() function and you will now see it shows the new directory as intended ‘public_html’

If you want to store files in the public_html folder you can modify the config/filesystems.php file like so:

'public' => [
            'driver' => 'local',
            'root' => public_path('storage'),
            'url' => env('APP_URL').'/storage',
            'visibility' => 'public',
        ],

This would allow you to store files in the public_html/storage folder and access them via http://yourdomain.com/storage

I do not use mix but I am sure you would need to change the paths in the webpack.mix.js folder as well:

// From
mix.js('resources/assets/js/app.js', 'public/js')
   .sass('resources/assets/sass/app.scss', 'public/css');

// To
mix.js('resources/assets/js/app.js', '../public_html/js')
   .sass('resources/assets/sass/app.scss', '../public_html/css');

I hope this helps others looking to change the directory structure. If anyone has any other ways to accomplish this that will work better I would love to hear it.

Thank you for reading and your comments!

Regards,

Ray