Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

firewizard's avatar

Setup different frontend & backend endpoints in Laravel 5.1

I've been struggling figuring this out but no luck yet - couldn't find an answer anywhere.

I've posted this on Laravel.io & StackOverflow too, but no answer yet: http://laravel.io/forum/01-17-2016-setup-different-frontend-backend-application-endpoints & http://stackoverflow.com/questions/34865377/setup-different-frontend-backend-application-endpoints-in-laravel-5

I have a regular public-facing website for which I need an admin interface. Assuming the website is at example.com, I want the admin interface to be accessible from example.com:3000.

I've tried domain routing, it doesn't seem to be working. The idea is to share all the business logic, but isolate assets and routes - for instance, accessing "/" would produce different results on the frontend (showing the homepage) and on the backend (showing a dashboard). I also need different middleware authentication, but I have a hunch that's going to be easy once I figure out how to set this up.

If it's easy to add different sessions, that would also be cool, but I can live without it.

Any help or hint would be much appreciated, thanks.

0 likes
13 replies
RachidLaasri's avatar

Hi,

This is how you can structurer your Routes. Note that i am using the namespaces which means that my routes must be located in

  • Public Routes : App\Http\Controller\Frontend
  • Dashboard Routes : App\Http\Controller\Dashboard

And you can access your dashboard using http://site.com/dashboard, you can use any name you want by changing the the prefix in the route group.

Route::group(['namespace' => 'Frontend'], function(){

    get('/', [
        'as' => 'home',
        'uses' => 'HomeController@index'
    ]);

    // the rest of your public routes.

});

Route::group(['namespace' => 'Dashboard', 'prefix' => 'dashboard'], function() {

    get('/', [
        'as' => 'dashboard.home',
        'uses' => 'HomeController@index'
    ]);

    // the rest of your dashboard routes.

});
firewizard's avatar

Hey, thanks for the answer, but I'm afraid that's not what I'm looking for. That just creates two route groups, using prefix for the dashboard. I need to route the same path (say "/", or "pages") from both the admin panel and the frontend but get different results, based on the domain+port. So, domain.com/pages would show a list of pages, domain.com:3000/pages would allow the admins to delete & add pages - just a simple example. I've already tried prefixes, namespaces, subdomain routing, couldn't make it work. I've also tried different Kernels, feels like that's the correct approach, but I'm stuck - I'm not sure how to override the router (or some component) to make it aware of the "side" it's on: frontend or backend.

Snapey's avatar

can you place the routes inside a case switch that checks the server port attribute?

TylerODonnell's avatar
Level 28

I've done something similar before. You can pull it off by editing the app/Providers/RouteServiceProvider and loading in a specific routes file based on the "context" of the application.

You could create two routes files /app/Http/Routes/frontend.php and /app/Http/Routes/backend.php. You'll do some sort of logic in the RouteServiceProvider to determine what route file to load in.

Here's some pseudo code that can get you started.

namespace App\Providers;

use Illuminate\Routing\Router;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;

class RouteServiceProvider extends ServiceProvider
{
    /**
     * This namespace is applied to the controller routes in your routes file.
     *
     * In addition, it is set as the URL generator's root namespace.
     *
     * @var string
     */
    protected $namespace = 'App\Http\Controllers';
    /**
     * Define your route model bindings, pattern filters, etc.
     *
     * @param  \Illuminate\Routing\Router  $router
     * @return void
     */
    public function boot(Router $router)
    {
        //
        parent::boot($router);
    }
    /**
     * Define the routes for the application.
     *
     * @param  \Illuminate\Routing\Router  $router
     * @return void
     */
    public function map(Router $router)
    {
        // If the current port is 3000
        // $route = 'backend'
        // else
        // $route = 'frontend'

        $router->group(['namespace' => $this->namespace], function ($router) {
            require app_path("Http/Routes/${route}.php");
        });
    }
}
3 likes
firewizard's avatar

You're right, it was a good start, so thank you very much for your answers. I've done it as suggested by Tyler, with the only difference that I chose to use a context constant - something like define('APP_CONTEXT', 'frontend') (or backend) in the public and backend folders - the folders that act as document roots. Based on the context I'm doing the switch/if and registering only the required routes. It's hackish but it does the trick - now I have a few other things to solve, like different sessions, different view paths, different Auth models, but that's a different story.

Btw, if anyone's interested, this package seems like the correct way to do it: https://github.com/rtroncoso/Laravel-Context - I haven't used it and it seems a bit complicated, but I feel it's the best approach.

alvakoldo10's avatar

I was trying right the same but using subdomains like this in just one routes.php

Route::group(['domain' => 'frontend.mydomain.com'], function () {
        Route::get('/', 'WelcomeController@index');
        Route::group(['middleware' => ['web']], function () {
                Route::auth();
        });
        Route::group(['middleware' => ['web','auth']], function () {
                Route::get('/home', 'HomeController@index');
                Route::group(['prefix' => 'record'], function () {
                        Route::get('all','RecordController@all');
                });
        });
});

Route::group(['domain' => 'backend.mydomain.com'], function () {
        Route::get('/', 'WelcomeController@index');
        Route::group(['middleware' => ['web']], function () {
                Route::auth();
        });
        Route::group(['middleware' => ['web','auth']], function () {
                Route::get('/home', 'HomeController@index');
                Route::group(['prefix' => 'record'], function () {
                        Route::get('all','RecordController@all');
                });
        });
});

However some kinda loop or mix via cookie is not isolating my 2 subdomains :( .....do not why as I've already set 'domain' => '.mydomain.com' at my config/session.php. Any clue ?

Any way, trying your approch, I get 404 for all routes like mydomain.com:3000 ....investigating why at the moment

firewizard's avatar

@alvakoldo10 - subdomain routing works out of the box with L5. it does not isolate cookies or sessions, but you can easily setup routes. However, things get trickier when using ports, hence my initial question. The short answer is you don't need server ports, your application should be domain agnostic. Your web server should point to different doc roots (such as public for frontend website and admin for backend, for instance). If you add an API on top of this, you could have a 3rd doc root.

I solved this by having different Kernels - one for the front and one for the back. The kernels load all the default bootstrappers, but they also load their own stuff - for instance the backend kernel could load an additional config parser/loader that takes some backend config overwrites and merges them with the main config.

Based on you example, when accessing frontend.mydomain.com the application loads as usual, with the default Laravel stuff in in. But when one uses backend.mydomain.com, the extra bootrappers look at a few extra configuration files that instruct the application to overwrite some of the defaults - auth middleware, views paths, session names, etc. I've also added "app.context" which is then used to create routes separation - this could be achieved with loading different Service Providers, which seems more appropriate in terms of architecture, but that seems like too much of a headache for now.

So now I can load different controllers/routes and use different views, based on the current vhost.

1 like
alvakoldo10's avatar

Great ! thanks for your quick answer @firewizard :)

I agree with no needing to use different server ports for my purpose however, when you say

"Your web server should point to different doc roots ..."

That involves 2 different Laravel applications, which is not what I'd like. I can do at web-server level (nginx) whatever is needed for my purpose - but as for the Laravel5 level ...do not know still how to achieve my purpose :

1.- just one L5 app. 2.- Isolated backend and frontend routes/logic 3.- Same database for front and backend but different table for each one's users (that's why I meant a different auth guard like shown below)

...
        Route::group(['middleware' => ['web','auth:admin']], function () {
...

Not sure If understand your answer as I try to re-read it once again ...

christopher's avatar

I made a new Folder caled Routes inside my App/Http Folder. Then i created two files. frontend.php & backend.php

I included this files inside my routes.php. My routes.php looks like this

<?php

Route::group(['namespace' => 'frontend'], function()
{
    include_once(app_path() . '/Http/Routes/frontend.php');
});

Route::group(['namespace' => 'backend'], function()
{
    include_once(app_path() . '/Http/Routes/backend.php');
});
....
firewizard's avatar

No need for two applications, that wasn't my intent either. I need one laravel installation, handling the website and its backend interface. Pretty common and straightforward, except for that special port setup.

Let me detail what I meant by 2 doc roots. The default folder structure is this:

app
bootstrap
config
database
public
resources
storage
tests
vendor

Now, the public folder is the default doc root. That's the main application entry point. But no one says you can't have more than one. Just add admin (or any other name you'd like), copy and tweak .htaccess and index.php, add your static resources if you want, then configure nginx to have two vhosts - one pointing to public, the other one to admin.

with this approach, all of your requirements are met.

You might also want to take a look at this plugin: https://github.com/rtroncoso/Laravel-Context - although I find it a bit difficult to use.

alvakoldo10's avatar

@firewizard thanks a lot for your attention. I've tried your suggestion altough I did not see the point of it. Indeed, I surely missed something as nothing got better :(, it did'nt actually get isolated auth methods for frontend and backend

Anyway your suggestions have helped me to try it another way and nearly get it all right !! I'll try to resume my steps (hope not to miss nothing):

//1.-  Fresh out-of-the-box L5 Installation

//2.- php artisan make:auth  to get all the basic controllers, views, etc ... for Auth

//3.- Modification of AuthController as follows
    .....
    protected $guard = 'web';
    .....
    public function __construct()
    {
        $this->middleware('guest', ['except' => 'logout']);
        if(stristr($_SERVER['HTTP_HOST'],'backend')) $this->guard = 'admin';
    }

//4.- Indicated in config/auth.php requested classes (also implemented), providers, guards ...

        'guards' => [
                'web' => [
                        'driver' => 'session',
                        'provider' => 'users',
                ],
                //my custom
                'admin' => [
                        'driver' => 'session',
                        'provider' => 'admin',
                ],
                'api' => [
                        'driver' => 'token',
                        'provider' => 'users',
                ],
        ],
    ....

        'providers' => [
                'users' => [
                        'driver' => 'eloquent',
                        'model' => App\User::class,
                ],
        //My custom
                'admin' => [
                        'driver' => 'eloquent',
                        'model' => App\AdminUser::class,
                ],
        ],
    
//5.- Isolated routes by subdomains at routes.php 
    Route::group(['domain' => 'frontend.mydomain.com'], function () {
    // ...all the frontend routes
    });
    Route::group(['domain' => 'backend.mydomain.com'], function () {
    // ...all the backend routes
    });

Up here' I've nearly got what I need :: frontend.mydomain.com and backend.mydomain.com using different tables (and User / AdminUser classes) to Authenticate. HOWEVER, still work to do as my admin views show Auth::user() object is null. I suspect I did not tell my L5 application how to load user my app\AdminUser ......getting closer ......hope not to die struggling so much time :)

firewizard's avatar

This seems like L5.2 to me. I'm using 5.1. There might be some differences.

And your code looks right, not sure why Auth::user returns null.

alvakoldo10's avatar

Yeah it is 5.2, and the point is the custom guard; at last simple, although hard to find and understand the different logic.

If you use another guard, you must do following to access the user

Auth::guard('your_guard_name_as_defined_in_config_auth.php')->user()

Thanks @firewizard for your attention

Please or to participate in this conversation.