ethar's avatar
Level 5

Laravel 10 Change public folder to public_html on shared server

I'm using a shared hosting which uses cPanel as its control panel and within the cPanel public_html is the default root directory, because of this I can't get my Laravel application work properly.

Is there any way to make Laravel use public_html instead of public folder?

i try to use this 2 way in index.php I add this code

$app = require_once __DIR__.'/../code/bootstrap/app.php';
$kernel = $app->make(Kernel::class);
$app->bind('path.public', function() {
    return __DIR__;
});

in appServiceProvider I add this code

    public function register(): void
    {
        Paginator::useBootstrap();
        $this->app->bind('path.public', function() {
            return base_path('public_html');
        });
    }

but not working

0 likes
13 replies
ethar's avatar
Level 5

@jlrdw for laravel 9 and before its worked successfully, but not working in laravel 10

martinbean's avatar

@ethar Simple as modifying your bootstrap/app.php file.

After this section:

$app = new Illuminate\Foundation\Application(
    $_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
);

Put:

$app->usePublicPath($app->basePath('public_html'));
8 likes
armandoaepp's avatar

@martinbean muchas gracias por la la info.

a mi se sirvio de esta forma.

  1. En public_html -> copiar los archivos de la carpeta publica
  2. En la una carpeta de la raiz por ejemplo core_app(carpete) va todo lo que contiene el framework.

$app = new Illuminate\Foundation\Application( $_ENV['APP_BASE_PATH'] ?? dirname(DIR) );

$app->usePublicPath($app->basePath('../public_html'));

ojo la carpeta public_html y core_app , estan en la raiz

EL ARCHIVO index.php de la carpeta public_html

/* |-------------------------------------------------------------------------- | Check If The Application Is Under Maintenance |-------------------------------------------------------------------------- | | If the application is in maintenance / demo mode via the "down" command | we will load this file so that any pre-rendered content can be shown | instead of starting the framework, which could cause an exception. | */

if (file_exists($maintenance = DIR.'/../core_imprex/storage/framework/maintenance.php')) { require $maintenance; }

/* |-------------------------------------------------------------------------- | Register The Auto Loader |-------------------------------------------------------------------------- | | Composer provides a convenient, automatically generated class loader for | this application. We just need to utilize it! We'll simply require it | into the script here so we don't need to manually load our classes. | */

require DIR.'/../core_imprex/vendor/autoload.php';

/* |-------------------------------------------------------------------------- | Run The Application |-------------------------------------------------------------------------- | | Once we have the application, we can handle the incoming request using | the application's HTTP kernel. Then, we will send the response back | to this client's browser, allowing them to enjoy our application. | */

$app = require_once DIR.'/../core_imprex/bootstrap/app.php';

1 like
techyad's avatar

@martinbean After hours of searching and testing different solution your answer finally worked for me

I am using Laravel 10 latest version and php 8.1

1 like
muuucho's avatar

@martinbean Thanks. When I try to rename my folder "public" to "public_html" in PHPStorm, I get a message

java.io.IOException: Cannot rename "path-to-public\public" to "public_heml".

EDIT: Found it: Close all uses of the project, including PHP bult in server. Then rename.

Stephan__MC's avatar

add the following in the bootstrap/app.php. Make sure it is added after initialising the $app

$app->usePublicPath(realpath(base_path('/../public_html')));

this line will cause your appliccation to use the specified public_html directory if it exists otherwise will use laravel's default public direcory.

thereby causing your app to work both in production or local.

1 like
Snapey's avatar

if you have terminal access to your server;

  • place your laravel project in a folder above public_html. Change NOTHING about your project.

  • delete public_html entirely. Recreate it as a symlink to your laravel public folder

if you don't have terminal access to your server, get a better host

see https://hafizmohammed.medium.com/how-to-deploy-laravel-in-cpanel-the-right-way-78d0a767d5a2

or my series of articles here: https://laravelsharedhosting.novate.co.uk/

2 likes
imade's avatar

I think i'ts best to change the public path in the bootstrap/app.php so that both console and app are affected by the change.

In Laravel 11 you can use the registered method:

return Application::configure(basePath: dirname(__DIR__))
    ->registered(function ($app) {
        $app->usePublicPath(path: realpath(base_path('/../public_html')));
    })
    ->withRouting(
        web: __DIR__ . '/../routes/web.php',
        commands: __DIR__ . '/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        //
    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();
```
5 likes
Zephni's avatar

@imade Thanks, I was looking for the laravel 11 way of doing this. However sadly I'm still getting an error when trying to serve the application. This is my bootstrap/app.php which seems correct to me:

return Application::configure(basePath: dirname(__DIR__))
    ->registered(function ($app) {
        $app->usePublicPath(path: realpath(base_path('/../public_html')));
    })...

But when trying to run php artisan serve on a brand new application (with public/ changed to public_html/) I get this error:

C:\Craig\Websites\ibis-hse.com> php artisan serve

   Symfony\Component\Process\Exception\RuntimeException 

  The provided cwd "C:\Craig\Websites\ibis-hse.com\public" does not exist.

  at vendor\symfony\process\Process.php:339
    335▕             }
    336▕         }
    337▕
    338▕         if (!is_dir($this->cwd)) {
  ➜ 339▕             throw new RuntimeException(sprintf('The provided cwd "%s" does not exist.', $this->cwd));
    340▕         }
    341▕
    342▕         $process = @proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $envPairs, $this->options);
    343▕

  1   vendor\laravel\framework\src\Illuminate\Foundation\Console\ServeCommand.php:154
      Symfony\Component\Process\Process::start(Object(Closure))

  2   vendor\laravel\framework\src\Illuminate\Foundation\Console\ServeCommand.php:93
      Illuminate\Foundation\Console\ServeCommand::startProcess()

I also tried binding public.path within the AppServiceProvider, and also ran php artisan optimize:clear just incase there was a caching issue, but it's weird that it's still trying to look for basedir/public/ even though when doing a Ctrl+Shift+F and looking for the word public in the entire application there is nowhere that it is specified other than the storage filesystem stuff. So why dyu think it's ignoring the app bindings etc?

Any help would be greatly appreciated thank you!

z3phir's avatar

@zephni you can do ->usePublicPath(base_path('public_html')) after create. you can chain a lot of stuff here like ->loadEnvironmentFrom('customenv')

1 like
Zephni's avatar

@z3phir Thanks, so sorry I thought I had already replied, but that worked! Appreciate it :)

Please or to participate in this conversation.