MrDKOz
MrDKOz

Reputation: 357

Laravel Controller to Controller

I've built a website using Laravel that I'm happy with, however, due to not planning ahead I have built the admin/management panel, and now that I have to go through and do the user front end I'm wondering how I should have though to handle this.

Currently I have a web.php file containing lines like this:

# WEDDING HANDLING
Route::get('/admin/weddings', 'WeddingController@index');
Route::get('/admin/wedding/create', 'WeddingController@create');
Route::get('/admin/wedding/{wedding}', 'WeddingController@show');
Route::get('/admin/wedding/{wedding}/edit', 'WeddingController@edit');

Route::post('/admin/wedding/create', 'WeddingController@store');
Route::put('/admin/wedding/{wedding}/edit', 'WeddingController@update');
Route::delete('/admin/wedding/{wedding}/destroy', 'WeddingController@destroy');

# MENU HANDLING
Route::get('/admin/wedding/{wedding}/menus', 'MenuController@index');
Route::get('/admin/wedding/{wedding}/menu/create', 'MenuController@create');
Route::get('/admin/wedding/{wedding}/menu/{menu}', 'MenuController@show');
Route::get('/admin/wedding/{wedding}/menu/{menu}/edit', 'MenuController@edit');

Route::post('/admin/wedding/{wedding}/menu/create', 'MenuController@store');
Route::put('/admin/wedding/{wedding}/menu/{menu}/edit', 'MenuController@update');
Route::delete('/admin/wedding/{wedding}/menu/{menu}/delete', 'MenuController@destroy');
...continues

So from that you can probably see that I have multiple controllers that handle this for the admin, however, if a user logs in, they should be able to view the menus against the wedding, which I can stack with @auth tags, and seperate it out like that, however I'm afraid I'm going to end up with a web.php that looks like the following:

# WEDDING HANDLING
Route::get('/admin/weddings', 'WeddingController@index');
Route::get('/weddings', 'WeddingController@index');
...continues

Hopefully from my demo you can see what I'm asking.

tl;dr: How would you go about seperating User/Management areas without duplicating a ton of code.

Upvotes: 0

Views: 333

Answers (4)

mdexp
mdexp

Reputation: 3567

As you are almost adhering to the CRUD/REST convention, an addition to Adriano Marra's answer would be to also use resource controllers.

From Laravel documentation about resource controllers:

Laravel resource routing assigns the typical "CRUD" routes to a controller with a single line of code.


Introducing Resource Controllers

In your use case your resource are the weddings, so you could rewrite your web.php routes as:

Route::prefix('admin')->group(function () {
    Route::resource('weddings', 'WeddingsController');
});

These lines would register such routes:

+--------+-----------+-------------------------------+------------------+-------------------------------------------------+------------+
| Domain | Method    | URI                           | Name             | Action                                          | Middleware |
+--------+-----------+-------------------------------+------------------+-------------------------------------------------+------------+
|        | GET|HEAD  | admin/weddings                | weddings.index   | App\Http\Controllers\WeddingsController@index   | web        |
|        | POST      | admin/weddings                | weddings.store   | App\Http\Controllers\WeddingsController@store   | web        |
|        | GET|HEAD  | admin/weddings/create         | weddings.create  | App\Http\Controllers\WeddingsController@create  | web        |
|        | GET|HEAD  | admin/weddings/{wedding}      | weddings.show    | App\Http\Controllers\WeddingsController@show    | web        |
|        | PUT|PATCH | admin/weddings/{wedding}      | weddings.update  | App\Http\Controllers\WeddingsController@update  | web        |
|        | DELETE    | admin/weddings/{wedding}      | weddings.destroy | App\Http\Controllers\WeddingsController@destroy | web        |
|        | GET|HEAD  | admin/weddings/{wedding}/edit | weddings.edit    | App\Http\Controllers\WeddingsController@edit    | web        |
+--------+-----------+-------------------------------+------------------+-------------------------------------------------+------------+

NOTE: There's a small difference as the Route::resource(...) method uses the plural resource name you provided to it (weddings) for all the seven routes, and the singular form for the parameter name (wedding).

You could then register the menus resource in the same way:

Route::prefix('admin')->group(function () {
    Route::resource('weddings', 'WeddingsController');

    // Personally, I would make 'menus' a top level resource but I will
    // stick to your routing example for the rest of the answer.
    Route::resource('weddings/{wedding}/menus', 'WeddingMenusController');
});

Named Group Resource Routes

Furthermore you could also register the frontend wedding controller as a resource

Route::prefix('admin')->group(function () {
    Route::resource('weddings', 'WeddingsController');
    Route::resource('weddings/{wedding}/menus', 'WeddingMenusController');
});

// This will map only two methods for this resource.
Route::resource('weddings', 'FrontendController')->only(['index', 'show']);

The routes registered by your application would be:

+--------+-----------+--------------------------------------------+------------------+-------------------------------------------------+------------+
| Domain | Method    | URI                                        | Name             | Action                                          | Middleware |
+--------+-----------+--------------------------------------------+------------------+-------------------------------------------------+------------+
|        | GET|HEAD  | admin/weddings                             | weddings.index   | App\Http\Controllers\WeddingsController@index   | web        |
|        | POST      | admin/weddings                             | weddings.store   | App\Http\Controllers\WeddingsController@store   | web        |
|        | GET|HEAD  | admin/weddings/create                      | weddings.create  | App\Http\Controllers\WeddingsController@create  | web        |
|        | GET|HEAD  | admin/weddings/{wedding}                   | weddings.show    | App\Http\Controllers\WeddingsController@show    | web        |
|        | PUT|PATCH | admin/weddings/{wedding}                   | weddings.update  | App\Http\Controllers\WeddingsController@update  | web        |
|        | DELETE    | admin/weddings/{wedding}                   | weddings.destroy | App\Http\Controllers\WeddingsController@destroy | web        |
|        | GET|HEAD  | admin/weddings/{wedding}/edit              | weddings.edit    | App\Http\Controllers\WeddingsController@edit    | web        |
|        | GET|HEAD  | admin/weddings/{wedding}/menus             | menus.index      | App\Http\Controllers\WeddingsController@index   | web        |
|        | POST      | admin/weddings/{wedding}/menus             | menus.store      | App\Http\Controllers\WeddingsController@store   | web        |
|        | GET|HEAD  | admin/weddings/{wedding}/menus/create      | menus.create     | App\Http\Controllers\WeddingsController@create  | web        |
|        | GET|HEAD  | admin/weddings/{wedding}/menus/{menu}      | menus.show       | App\Http\Controllers\WeddingsController@show    | web        |
|        | PUT|PATCH | admin/weddings/{wedding}/menus/{menu}      | menus.update     | App\Http\Controllers\WeddingsController@update  | web        |
|        | DELETE    | admin/weddings/{wedding}/menus/{menu}      | menus.destroy    | App\Http\Controllers\WeddingsController@destroy | web        |
|        | GET|HEAD  | admin/weddings/{wedding}/menus/{menu}/edit | menus.edit       | App\Http\Controllers\WeddingsController@edit    | web        |
|        | GET|HEAD  | weddings                                   | weddings.index   | App\Http\Controllers\FrontendController@index   | web        |
|        | GET|HEAD  | weddings/{wedding}                         | weddings.show    | App\Http\Controllers\FrontendController@show    | web        |
+--------+-----------+--------------------------------------------+------------------+-------------------------------------------------+------------+

If you look close at the above table, you will notice that the name column has some duplicate values. This would create conflict when you need to reference these particular routes by name anywhere in your application.

So you could solve this by prefixing the admin group's named routes with a custom prefix:

Route::prefix('admin')->name('admin.')->group(function () {
    Route::resource('weddings', 'WeddingsController');
    Route::resource('weddings/{wedding}/menus', 'WeddingMenusController');
});

// This will map only two methods for this resource.
Route::resource('weddings', 'FrontendController')->only(['index', 'show']);

This would solve any route conflict, as the administation routes has been correctly prefixed with admin. name:

+--------+-----------+--------------------------------------------+------------------------+-------------------------------------------------+------------+
| Domain | Method    | URI                                        | Name                   | Action                                          | Middleware |
+--------+-----------+--------------------------------------------+------------------------+-------------------------------------------------+------------+
|        | GET|HEAD  | admin/weddings                             | admin.weddings.index   | App\Http\Controllers\WeddingsController@index   | web        |
|        | POST      | admin/weddings                             | admin.weddings.store   | App\Http\Controllers\WeddingsController@store   | web        |
|        | GET|HEAD  | admin/weddings/create                      | admin.weddings.create  | App\Http\Controllers\WeddingsController@create  | web        |
|        | GET|HEAD  | admin/weddings/{wedding}                   | admin.weddings.show    | App\Http\Controllers\WeddingsController@show    | web        |
|        | PUT|PATCH | admin/weddings/{wedding}                   | admin.weddings.update  | App\Http\Controllers\WeddingsController@update  | web        |
|        | DELETE    | admin/weddings/{wedding}                   | admin.weddings.destroy | App\Http\Controllers\WeddingsController@destroy | web        |
|        | GET|HEAD  | admin/weddings/{wedding}/edit              | admin.weddings.edit    | App\Http\Controllers\WeddingsController@edit    | web        |
|        | GET|HEAD  | admin/weddings/{wedding}/menus             | admin.menus.index      | App\Http\Controllers\WeddingsController@index   | web        |
|        | POST      | admin/weddings/{wedding}/menus             | admin.menus.store      | App\Http\Controllers\WeddingsController@store   | web        |
|        | GET|HEAD  | admin/weddings/{wedding}/menus/create      | admin.menus.create     | App\Http\Controllers\WeddingsController@create  | web        |
|        | GET|HEAD  | admin/weddings/{wedding}/menus/{menu}      | admin.menus.show       | App\Http\Controllers\WeddingsController@show    | web        |
|        | PUT|PATCH | admin/weddings/{wedding}/menus/{menu}      | admin.menus.update     | App\Http\Controllers\WeddingsController@update  | web        |
|        | DELETE    | admin/weddings/{wedding}/menus/{menu}      | admin.menus.destroy    | App\Http\Controllers\WeddingsController@destroy | web        |
|        | GET|HEAD  | admin/weddings/{wedding}/menus/{menu}/edit | admin.menus.edit       | App\Http\Controllers\WeddingsController@edit    | web        |
|        | GET|HEAD  | weddings                                   | weddings.index         | App\Http\Controllers\FrontendController@index   | web        |
|        | GET|HEAD  | weddings/{wedding}                         | weddings.show          | App\Http\Controllers\FrontendController@show    | web        |
+--------+-----------+--------------------------------------------+------------------------+-------------------------------------------------+------------+

Namespacing Groups

Finally, you could go further with optimizations with introduction of namespaces (useful if you start to have more and more controllers).

You can create a folder in you app/Http/Controllers, for example Administration, where you store all of your administrative controllers.

In the web.php file, you just have to tell Laravel that the admin prefixed route group should look for controllers in the newly created folder:

Route::prefix('admin')->namespace('Administration')->name('admin.')->group(function () {
    Route::resource('weddings', 'WeddingsController');
    Route::resource('weddings/{wedding}/menus', 'WeddingMenusController');
});

// This will map only two methods for this resource.
Route::resource('weddings', 'FrontendController')->only(['index', 'show']);

This would lead to register these routes:

+--------+-----------+--------------------------------------------+------------------------+----------------------------------------------------------------+------------+
| Domain | Method    | URI                                        | Name                   | Action                                                         | Middleware |
+--------+-----------+--------------------------------------------+------------------------+----------------------------------------------------------------+------------+
|        | GET|HEAD  | admin/weddings                             | admin.weddings.index   | App\Http\Controllers\Administration\WeddingsController@index   | web        |
|        | POST      | admin/weddings                             | admin.weddings.store   | App\Http\Controllers\Administration\WeddingsController@store   | web        |
|        | GET|HEAD  | admin/weddings/create                      | admin.weddings.create  | App\Http\Controllers\Administration\WeddingsController@create  | web        |
|        | GET|HEAD  | admin/weddings/{wedding}                   | admin.weddings.show    | App\Http\Controllers\Administration\WeddingsController@show    | web        |
|        | PUT|PATCH | admin/weddings/{wedding}                   | admin.weddings.update  | App\Http\Controllers\Administration\WeddingsController@update  | web        |
|        | DELETE    | admin/weddings/{wedding}                   | admin.weddings.destroy | App\Http\Controllers\Administration\WeddingsController@destroy | web        |
|        | GET|HEAD  | admin/weddings/{wedding}/edit              | admin.weddings.edit    | App\Http\Controllers\Administration\WeddingsController@edit    | web        |
|        | GET|HEAD  | admin/weddings/{wedding}/menus             | admin.menus.index      | App\Http\Controllers\Administration\WeddingsController@index   | web        |
|        | POST      | admin/weddings/{wedding}/menus             | admin.menus.store      | App\Http\Controllers\Administration\WeddingsController@store   | web        |
|        | GET|HEAD  | admin/weddings/{wedding}/menus/create      | admin.menus.create     | App\Http\Controllers\Administration\WeddingsController@create  | web        |
|        | GET|HEAD  | admin/weddings/{wedding}/menus/{menu}      | admin.menus.show       | App\Http\Controllers\Administration\WeddingsController@show    | web        |
|        | PUT|PATCH | admin/weddings/{wedding}/menus/{menu}      | admin.menus.update     | App\Http\Controllers\Administration\WeddingsController@update  | web        |
|        | DELETE    | admin/weddings/{wedding}/menus/{menu}      | admin.menus.destroy    | App\Http\Controllers\Administration\WeddingsController@destroy | web        |
|        | GET|HEAD  | admin/weddings/{wedding}/menus/{menu}/edit | admin.menus.edit       | App\Http\Controllers\Administration\WeddingsController@edit    | web        |
|        | GET|HEAD  | weddings                                   | weddings.index         | App\Http\Controllers\FrontendController@index                  | web        |
|        | GET|HEAD  | weddings/{wedding}                         | weddings.show          | App\Http\Controllers\FrontendController@show                   | web        |
+--------+-----------+--------------------------------------------+------------------------+----------------------------------------------------------------+------------+

Upvotes: 2

Vipertecpro
Vipertecpro

Reputation: 3274

This is what i do when i need to separate admin and front end routes

Route::group([
        'prefix'          => 'admin',
        'namespace'       => 'Admin', // assumed
        // 'as'           => 'admin.'  
        // 'middleware'   => 'admin.'  
    ], function () {

        Route::get('weddings', 'WeddingController@index');

        Route::group([
            'prefix'       => 'wedding',
        ], function () {
            // Wedding Management
            Route::get('{wedding}/show', 'WeddingController@show'); // Updated with /show in url otherwise it will overlap create

            Route::get('{wedding}/edit', 'WeddingController@edit');
            Route::put('{wedding}/edit', 'WeddingController@update');

            Route::delete('{wedding}/destroy', 'WeddingController@destroy');

            Route::get('create', 'WeddingController@create');
            Route::post('create', 'WeddingController@store');

            // Here you differentiate WeddingController and MenuController

            // Route::group([
            //    'middleware'       => 'only_applied_to_this_group',
            // ], function () {
                    // Menu Management
                    Route::get('{wedding}/menus', 'MenuController@index');
                    Route::get('{wedding}/menu/create', 'MenuController@create');
                    Route::get('{wedding}/menu/{menu}', 'MenuController@show');
                    Route::get('{wedding}/menu/{menu}/edit', 'MenuController@edit');

                    Route::post('{wedding}/menu/create', 'MenuController@store');
                    Route::put('{wedding}/menu/{menu}/edit', 'MenuController@update');
                    Route::delete('{wedding}/menu/{menu}/delete', 'MenuController@destroy')
            // });
        });
    });

    Route::group([
        'namespace'    => 'Front',
        'as'           => 'front.'
    ], function () {
        // Front-end Management
    });

I tried to make it more simplified for better routes understanding, i hope this works.

Upvotes: 0

Adriano Marra
Adriano Marra

Reputation: 129

You would need to create different controllers just to handle the front-end, like: FrontEndMenuController@yourFunction

you could also separate your admin routes into a group with the prefix 'admin' instead of repeating it on all the routes:

Route::prefix('admin')->group(function () {
   Route::get('/wedding/{wedding}/menus', 'MenuController@index');
   Route::get('/wedding/{wedding}/menu/create', 'MenuController@create');
   Route::get('/wedding/{wedding}/menu/{menu}', 'MenuController@show');
   Route::get('/wedding/{wedding}/menu/{menu}/edit', 'MenuController@edit');
});

And then have your front-end routes like that:

Route::get('/wedding/{wedding}/menu', 'FrontEndMenuController@index');

Upvotes: 3

Jamie Burton
Jamie Burton

Reputation: 515

You can create a new FrontEndController, and route any front end pages to that controller.

Route::get('/admin/weddings', 'WeddingController@index');
Route::get('/weddings', 'FrontEndControllerController@showWeddings');

Then you can use middlewear to diferentiate and refactor any repeated code into the Wedding model and just call that.

Upvotes: 2

Related Questions