Laravel — P56: Dependency Injection in Controllers

Inject services, unclutter your controllers

Since we just tackled everything route related, the next logical step is to get into Controllers. There are those that would have argued that we should have covered migrations, Models and then Controllers/Routes/Views, and there’s no disagreeing with that statement. Maybe I should write two Laravel article series concurrently. In the routing concept, without getting too far into the weeds, the Controller comes next.

https://www.dinocajic.com/laravel-p55-soft-deleted-models-in-routes/

It’s not that we haven’t covered controllers yet, we just haven’t dug into some of the more infrequently/complicated functionality yet. Most of the concepts that we have already covered in routes translate over to controllers, like dependency injections, so what better place to start than discussing Dependency Injection in Laravel Controllers.

To recap dependency injection in general, take a look at the following articles.

https://www.dinocajic.com/laravel-p48-dependency-injection-concept-high-level-php-concept/

https://www.dinocajic.com/laravel-p49-dependency-injection/

https://www.dinocajic.com/laravel-p50-routing-and-dependency-injection/

An interesting concept to remember is that the Service Container is used to resolve all Laravel controllers. Since it does so, we can type-hint any dependencies that the controller may need through the constructor or through a specific method. You might remember the following dependency injection example.

<?php

namespace App\Http\Controllers;

use App\Services\CapitalizeStringService;
use Illuminate\Http\Request;

class DependencyInjectionTestController extends Controller
{
    public function index(Request $request, CapitalizeStringService $capitalizeStringService)
    {
        $upper = $capitalizeStringService->capitalize( $request->input('name') );

        return $upper;
    }

    public function test()
    {
        $request = app()->make(Request::class);
        $capitalizeStringService = app()->make(CapitalizeStringService::class);

        $upper = $capitalizeStringService->capitalize( $request->input('name') );

        return $upper;
    }
}

In the index method, we type-hinted the CapitalizeStringService class. We then used it directly inside of the index method without having to instantiate the CapitalizeStringService class. The CapitalizeStringService class is an extremely basic class. It just capitalizes the string.

<?php

namespace App\Services;

class CapitalizeStringService
{
    public function capitalize($string)
    {
        return strtoupper($string);
    }
}

Without even fully discussing it, this is the concept of Dependency Injection in controllers. Let’s create another controller and inject a dependency through our constructor. Since we already have a simple class that we can inject, we’ll use the same CapitalizeStringService class.

# php artisan make:controller AnotherDependencyInjectionController

   INFO  Controller [app/Http/Controllers/AnotherDependencyInjectionController.php] created successfully.  

#

Next, we need to create our constructor that injects CapitalizeStringService through type-hinting and another method that consumes it.

<?php

namespace App\Http\Controllers;

use App\Services\CapitalizeStringService;
use Illuminate\Http\Request;

class AnotherDependencyInjectionController extends Controller
{
    private CapitalizeStringService $capitalizeStringService;

    public function __construct(CapitalizeStringService $capitalizeStringService)
    {
        $this->capitalizeStringService = $capitalizeStringService;
    }

    public function index(Request $request, )
    {
        $upper = $this->capitalizeStringService->capitalize( $request->input('name') );

        return $upper;
    }
}

Next, we need a route to call it.

use App\Http\Controllers\AnotherDependencyInjectionController;

Route::get('/controller-dependency-injection', [AnotherDependencyInjectionController::class, 'index']);

When we visit our route, http://0.0.0.0/controller-dependency-injection?name=dino, we should see the following: DINO.

You may be asking yourself if we can delete the __construct() and just type-hint the property. The answer to that is no, you need to inject it through the constructor.

https://github.com/dinocajic/youtube-laravel

Laravel Series

Continue your Laravel Learning.

Laravel — P55: Soft Deleted Models in Routes

Route to trashed records with confidence

Laravel – P55: Routes Soft – Deleted Models

In part 55 of our Laravel series, learn how to work with soft-deleted Eloquent models inside routes. Configure bindings to include trashed records, build restore endpoints, and prevent 404 errors when referencing archived data.

Laravel — P56: Dependency Injection in Controllers

Inject services, unclutter your controllers

Laravel – P56: Dependency Injection In Controllers

In part 56 of our Laravel series, deep-dive into leveraging the framework’s service container directly inside controllers. See how constructor and method injection reduce boilerplate, improve testability, and keep your business logic sharply focused.

 

Secure actions with controller-level middleware

Laravel – P57: Middleware In Controllers

In part 57 of our Laravel series, discover how to register and apply middleware directly within controllers. Learn to secure sensitive actions, share common logic, and override route defaults for concise, maintainable code.

Leave a Reply