Back to Course |
How to Create Laravel Package: Step-by-Step Example

Our First Controller and Route

Let's finally test if our package does something (anything, really), by creating a Controller.

Let's create this file manually, cause it's not worth using make:controller - you would spend more time changing the namespaces and removing the default BaseController functionality if you don't need it.

So, we create a separate src/Http/Controllers subfolder inside our package, and create this:

packages/laraveldaily/laravel-permission-editor/src/Http/Controllers/RoleController.php:

namespace Laraveldaily\LaravelPermissionEditor\Http\Controllers;
 
use Illuminate\Routing\Controller;
 
class RoleController extends Controller
{
 
public function index()
{
return 'It works!';
}
 
}

Important note: we extend from the Illuminate\Routing\Controller from Laravel core, but the default Laravel project extends their Controllers from the BaseController in the app/Http/Controllers folder. In some cases, some packages may need the same functionality as that Controller's traits, but in our case, we don't need it, so the core Laravel Routing Controller is fine.

Now, how do we create a Route for what Controller? Simply by creating a familiar routes/web.php file, just inside the package structure.

packages/laraveldaily/laravel-permission-editor/routes/web.php:

use Laraveldaily\LaravelPermissionEditor\Http\Controllers\RoleController;
use Illuminate\Support\Facades\Route;
 
Route::resource('roles', RoleController::class);

Notice: we're creating the routes outside of the /src folder of the package. You can think of the /src folder of the package as the /app folder in a typical Laravel application. So, there will/may be src/Models, src/Http, and other subfolders, but things like /resources or /routes go outside of the /src.

As you can see, we're loading the Controller, providing its full namespace, the one that we registered a bit earlier in the composer.json file.

Now, we need to register the routes. And here's the first time we actually make use of the Service Provider.

packages/laraveldaily/laravel-permission-editor/src/PermissionEditorServiceProvider.php:

use Illuminate\Support\Facades\Route;
 
class PermissionEditorServiceProvider extends ServiceProvider
{
public function boot()
{
Route::prefix('permission-editor')
->as('permission-editor.')
->group(function () {
$this->loadRoutesFrom(__DIR__ . '/../routes/web.php');
});
}
}

So the routes are loaded with the $this->loadRoutesFrom() method, just providing the routes file.

In addition, I wrap those routes in the group immediately, to avoid conflicts with other routes of the application or other packages, so I assign the specific URL prefix and route name prefix to all the routes.

You can actually do that inside of the routes/web.php, too, but I prefer it in the Service Provider, as it's more like a global configuration setting than the Route behavior.

Now, we need to launch composer update to update all the functionality of the package in the main application. In case of success, you should see a line something like this:

  • Upgrading laraveldaily/laravel-permission-editor (dev-main cac9b96 => dev-main a066e56): Source already present

And now, we can launch the route /permission-editor/roles in our browser.

Laravel package - it works