Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Install multiple laravel projects in subfolders without subdomain

I already tried to search for this issue, but it's all different from mine, so I'm posting this here. I'm trying to create a webserver using nginx to host multiple laravel projects in subfolders. It's my labs server. So I'd like to have my projects like this:

  • domain.com/project1
  • domain.com/project2
  • domain.com/project3

I'm copying the following nginx location block for each project (i don't know what's happening here, I just copied from the internet and it worked):

location ^~ /project1/ {
        alias /home/web/project1/public;
        try_files $uri $uri/ @project1;

    location ~ \.php {
        fastcgi_pass                    unix:/var/run/php5-fpm.sock;
        fastcgi_index                   index.php;
        include                         /etc/nginx/fastcgi_params;
        fastcgi_param                   SCRIPT_FILENAME "/home/web/project1/public/index.php";
    }

}

location @project1 {
     rewrite /avm/(.*)$ /project1/index.php?/$1 last;
}

And RESTful routes in my laravel app like this:

/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the controller to call when that URI is requested.
|
*/

Route::get('/', ['middleware' => 'auth','uses' => 'HomeController@index'])->name('home');

// Authentication
Route::get('auth/login', 'Auth\AuthController@getLogin');
Route::post('auth/login', 'Auth\AuthController@authenticate');
Route::get('auth/logout', 'Auth\AuthController@getLogout');

// Administração
Route::group(['prefix' => 'administracao', 'middleware' => 'auth'], function() {
    Route::resource('filiais', 'FiliaisController');
    Route::resource('precos', 'PrecosController');
    Route::resource('funcionarios', 'FuncionariosController');
    Route::resource('cargos', 'CargosController');
    Route::resource('vendedores', 'VendedoresController');
});

// Comercial
Route::group(['prefix' => 'comercial', 'middleware' => 'auth'], function() {
    Route::resource('clientes', 'ClientesController');
    Route::resource('fichas', 'FichasController');
});

// Operacional
Route::group(['prefix' => 'operacional', 'middleware' => 'auth'], function() {
    Route::resource('agenda', 'AgendaController');
    Route::resource('os', 'OsController');
    Route::resource('ambientes', 'AmbientesController');
    Route::resource('processos', 'ProcessosController');
    Route::get('relatorios', 'RelatoriosController@index');

    Route::group(['prefix' => 'processo', 'middleware' => 'auth'], function() {
        Route::get('create', 'ProcessoController@create');
        Route::get('index', 'ProcessoController@index');

        Route::post('{os}/parse', 'ProcessoController@parse');

        Route::get('{os}', 'ProcessoController@principal');
        Route::match(['get', 'post'], '{os}/detalhe', 'ProcessoController@detalhe');
        Route::get('{os}/duplicidades', 'ProcessoController@duplicidades');
        Route::get('{os}/restantes', 'ProcessoController@restantes');
        Route::match(['get', 'post'], '{os}/auditoria', 'ProcessoController@auditoria');
        Route::match(['get', 'post'], '{os}/operadores', 'ProcessoController@operadores');
        Route::match(['get', 'post'], '{os}/divergencia', 'ProcessoController@divergencia');
        Route::match(['get', 'post'], '{os}/finalizar', 'ProcessoController@finalizar');
        Route::get('{os}/excluir/{setor}', 'ProcessoController@destroy');
    });
});

Although it seems to work (the page appears, etc) when it goes into bussiness logic (save to database, etc.) it appears to have many bugs. For example when I try to create a new employee in url http://domain.com/project1/administracao/funcionarios it gives me the error: SQLSTATE[42S22]: Column not found: 1054 Unknown column '/administracao/funcionarios' in (it's kinda prepending some url routes)

And when I setup a subdomain like project1.domain.com everything works fine. But I don't want to create a subdomain for each project, I want it to work in subfolders url. Is it possible?

like image 295
Rodrigo Souza Avatar asked Apr 04 '16 13:04

Rodrigo Souza


3 Answers

I have successfully run a Laravel 5.4 project in a "subfolder" of another site by using a simple symlink.

There was no funky special rewrite rules in the Nginx configuration. No copy & paste of sections of the project. No mention of the subfolder in the routes. Just a regular Laravel 5 project neatly contained somewhere on the server and a symlink to it's public folder from the main site's document root.

/var/www/domain.com/public/project1 --> /var/www/project1/public

All the routes just work!

When writing your views you do have to wrap the paths for client-side assets in asset() helper function so the paths in the HTML will contain the subfolder and the browser can find them.

<!-- Styles -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">

But doing that does not make your code less flexible, because if you do run the site in an environment where it is not accessed via a subfolder, it works because asset() works with what the address bar contains.

like image 115
Martin Joiner Avatar answered Nov 06 '22 05:11

Martin Joiner


Recently I had the exact same problem. I wanted to have

  • http://customerdemo.example.com/project1/
  • http://customerdemo.example.com/project2/
  • http://customerdemo.example.com/project3/

but I hated having to modify nginx conf every time I added a new project.

Here's what I came up with:

# Capture $project from /$projectname/controller/action
map $request_uri $project {

    ~^/(?<captured_project>[a-zA-Z0-9_-]+)/? $captured_project;
    default / ;
}

server {

    listen 11.22.33.44:80;

    server_name customerdemo.example.com www.customerdemo.example.com;

    # Use $project/public as root
    root /sites/customerdemo.example.com/$project/public;

    # Use index.php as directory index
    index index.php;

    # Include the basic h5bp config set (see https://github.com/h5bp/server-configs-nginx)
    include h5bp/basic.conf;

    # Process /projectname/the/rest/of/the/url
    location ~ ^/([^/]+)/(.*) {

        # Save the rest of the URL after project name as $request_url
        set $request_url /$2;


        # If the saved url refers to a file in public folder (a static file), serve it,
        # else redirect to index.php, passing along any ?var=val URL parameters
        try_files $request_url /index.php?$is_args$args;

    }

    # Process any URL containing .php (we arrive here through previous location block)
    # If you don't need to serve any other PHP files besides index.php, use location /index.php here
    # instead, to prevent possible execution of user uploaded PHP code
    location ~ [^/]\.php(/|$) {

        # Define $fastcgi_script_name and $fastcgi_path_info
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;

        # Immediately return 404 when script file does not exist
        if (!-f $document_root$fastcgi_script_name) {
            return 404;
        }

        # Mitigate https://httpoxy.org/ vulnerabilities
        fastcgi_param HTTP_PROXY "";

        # Define PHP backend location (find yours by grepping "listen ="
        # from your PHP config folder, e.g. grep -r "listen =" /etc/php/)
        fastcgi_pass unix:/run/php/php7.0-fpm.sock;

        # Set SCRIPT_FILENAME to execute
        fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;

        # Include the default fastcgi parameters
        include fastcgi_params;

        # Overwrite REQUEST_URI (default is $request_uri) with $request_url we saved earlier
        fastcgi_param  REQUEST_URI        $request_url;
    }

}

The result is that I don't have to do ANYTHING other than git clone in /sites/customerdemo.example.com/ folder and run composer install and php artisan migrate to add a new project.

Actually, I have developed myself a control panel where I can click on "Add project" and specify project details and a new bitbucket repo, mysql user and database will be created and customerdemo server will be given deploy access to this bitbucket repo and a webhook is set up in this new repo which will call a deployment script on customerdemo server each time someone commits to master on this repo which will trigger either git clone or git pull and composer install and database migration. That's why I needed dynamic Nginx configuration. ;-)

like image 35
Henno Avatar answered Nov 06 '22 04:11

Henno


Check this Nginx configuration I believe it will helps you

server {
server_name main-app.dev;
root /var/www/projects/main/public;


add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";

index index.html index.htm index.php;
charset utf-8;
# sub_directory
location ^~ /sub-app {
  alias /var/www/projects/sub/public;
  try_files $uri $uri/ @sub;

    location ~ \.php {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_read_timeout 30000;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME /var/www/projects/sub/public/index.php;
    }
    access_log off;
    error_log  /var/www/projects/sub/storage/log/error.log error;
}

location @sub {
   rewrite /sub/(.*)$ /sub/index.php?/$1 last;
} # end sub_directory

location / {
    try_files $uri $uri/ /index.php?$query_string;
}

location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt  { access_log off; log_not_found off; }

access_log off;
error_log  /var/www/projects/main/storage/log/error.log error;

error_page 404 /index.php;

location ~ \.php$ {
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_read_timeout 30000;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
}

location ~ /\.(?!well-known).* {
    deny all;
}}
like image 2
Hamza Alayed Avatar answered Nov 06 '22 03:11

Hamza Alayed