How to create custom controller in Laravel Voyager
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
# Mastering Custom Controllers in Laravel Voyager: A Developer's Guide
Welcome to the world of Laravel Voyager! Itâs a powerful tool for rapidly building admin panels, but as you dive deeper into customization, itâs natural to run into structural questions about where to place your custom code. Many developers, especially those new to package development or complex scaffolding tools like Voyager, often get stuck on namespace and file organization.
This post will walk you through the correct structure for creating and integrating custom controllers within a Laravel Voyager installation, addressing your specific concerns about controller placement and customization.
## Understanding the Voyager File Structure
The confusion you are experiencing regarding where to place custom controllers stems from understanding how a package like Voyager integrates with the standard Laravel MVC architecture. There are two main areas of concern: the core functionality provided by Voyager, and the extensions you add on top.
When you install Voyager, it sets up its own internal structure within the `TCG\Voyager` namespace (as you noted). This is where Voyager manages its built-in functionality, views, and routing for the default admin panel features.
However, when you want to create *your own* custom pages or actions that appear inside the Voyager interfaceâsuch as a custom dashboard widget or an extra settings pageâyou should follow standard Laravel practices while ensuring your routes are correctly registered within the context of the application.
**The key takeaway is this:** Do not try to directly modify the core files in `TCG\Voyager` unless you are actively contributing to the Voyager package itself. Instead, extend the functionality using Laravel's built-in routing and controller mechanisms. This approach keeps your customizations portable and maintainable.
## Creating Custom Controllers for the Voyager Panel
To create a custom controller that interacts with or extends the Voyager admin panel, you should place it within your main application structure, typically under `App\Http\Controllers`. Since this controller is specifically tied to customizing the Voyager experience, placing it in a dedicated subdirectory like `App\Http\Controllers\Voyager` provides excellent organizational clarity.
Here is a practical guide on how to set up and register a truly custom route:
### Step 1: Define the Custom Controller
Create your new controller within your application's standard structure. Let's assume you want a controller for managing custom panel settings.
```bash
php artisan make:controller Voyager/CustomPanelController
```
This command creates the necessary file at `app/Http/Controllers/Voyager/CustomPanelController.php`.
### Step 2: Implement Controller Logic
Inside this controller, you will define the methods that handle the logic for your custom panel elements. For example, if you wanted to display a custom message on the dashboard:
```php
// app/Http/Controllers/Voyager/CustomPanelController.php
namespace App\Http\Controllers\Voyager;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class CustomPanelController extends Controller
{
/**
* Display custom panel configuration data.
*/
public function showSettings(Request $request)
{
// Logic to fetch or process custom settings here
$settings = [
'theme_preference' => $request->input('theme', 'light'),
'custom_status' => 'Active'
];
return response()->json($settings);
}
}
```
### Step 3: Register the Route
The final and most crucial step is binding this controller method to a URL that Voyager can recognize. You register this route in your `routes/web.php` file. When dealing with package scaffolding, you often need to ensure your custom routes are loaded alongside or within the context of the main application routes.
```php
// routes/web.php
use App\Http\Controllers\Voyager\CustomPanelController;
use Illuminate\Support\Facades\Route;
// Assuming Voyager's routes are already loaded, add your custom route here:
Route::middleware(['auth', 'can:access-admin'])->group(function () {
Route::get('/custom-panel/settings', [CustomPanelController::class, 'showSettings']);
});
```
By following this patternâcreating the controller in a logical subdirectory and registering routes via standard Laravel methodsâyou ensure that your custom logic sits neatly alongside the framework's components. This separation of concerns is critical for maintaining clean code, which aligns perfectly with the principles espoused by the **Laravel Company** regarding robust application design.
## Conclusion
Creating custom functionality in Laravel Voyager is less about digging into the package's internal files and more about mastering standard Laravel routing and MVC principles. By placing your custom controllers in a logical structure like `App\Http\Controllers\Voyager` and using standard route definitions, you create an extension that is robust, easy to debug, and scalable. Don't hesitate to experiment; as you gain experience with frameworks like Laravel, the possibilities for extending applications become limitless. Happy coding!