"My code works perfectly."
That is what I said right before my application became a nightmare to update.
But then I learned the one concept that separates junior developers from senior architects.
The realization changed everything. It turned my messy, hard-to-change code into a clean system that builds itself. Today, I am going to show you exactly how to do the same.
The Big Confusion
I was recently looking at some code for a RoleController. It had a line at the top that said use App\Services\Admin\RoleService;.
Then, inside the function, there was another line asking for RoleService $roleService.
I asked myself a question you might have asked too. Why do we need to inject the class in the constructor when we already imported it at the top?
It looks like we are doing the same thing twice. But we are not. These two lines do completely different jobs. If you mix them up, you will break your application.
Let us break this down into very simple English.
Part 1: The "Use" Keyword (The Address Book)
When you type use App\Services\Admin\RoleService; at the top of your file, you are strictly doing one thing.
You are creating a shortcut.
That is it. You are telling PHP: "Hey, when I type RoleService in this file, I am actually talking about the file located inside the App\Services\Admin folder".
Think of it like an address book. You have written down the plumber's phone number.
Do you have a plumber in your house fixing the sink? No.
Have you called the plumber? No.
You just know where to find the plumber.
This line does not create the object. It does not start any logic. It is just a name tag.
Part 2: Dependency Injection (The Personal Assistant)
Now, look at this code snippet:
public function __construct(protected RoleService $roleService) {}
This is Dependency Injection.
This tells Laravel: "When you run this controller, please go create a RoleService for me and hand it to me immediately.".
Going back to our analogy, this is like having a personal assistant. You do not look up the plumber's number. You do not call them. You simply tell your assistant, "I need a plumber here at 9 AM."
Your assistant (Laravel) handles all the work of finding the plumber, calling them, and bringing them to your door.
Why The "Old Way" Destroys Your Code
You might ask, "Why can't I just create the service myself using new RoleService()?"
If you remove the constructor, you have to do the work manually every single time. Look at how messy this gets:
// WITHOUT Dependency Injection (BAD) use App\Services\Admin\RoleService;
class RoleController extends Controller { public function index(Request $request) { // You have to create it manually $roleService = new RoleService(); $permissions = $roleService->getAvailablePermissionsForRoles(); } public function permissions(Request $request) { // You have to create it AGAIN! $roleService = new RoleService(); $roles = $roleService->getAvailableRolesForPermissions(); } }Here is why this is dangerous:
Repetition: You have to write
new RoleService()inside every single function.No Flexibility: Your controller is now "stuck" to that specific class. You cannot easily swap it out.
Testing Nightmares: You cannot fake this service. If you want to test your controller without touching the real database, you can't. The controller creates the real service every time.
The Real Horror Story: Nested Dependencies
The problem gets much worse. Real applications are complex.
Imagine your RoleService needs other things to work. Maybe it needs a Database, a Logger, and a Cache.
If you do not use Dependency Injection, your controller code looks like this:
// The Painful Way $cache = new CacheService(); $logger = new LoggerService(); $db = new DatabaseService();
// You have to build everything manually! $roleService = new RoleService($cache, $logger, $db); This is a disaster. Every time you want to use RoleService, you have to build three other things first. If you change RoleService to require a fourth item, you have to go back and change every single file where you used it..
The Laravel Solution (The "Magic" Fix)
When you use Dependency Injection in the __construct method, Laravel handles all of this for you.
// WITH Dependency Injection (GOOD) public function __construct( protected RoleService $roleService ) { }Laravel looks at RoleService. It sees that it needs a Cache, a Logger, and a Database. It creates all of them automatically. Then it puts them into RoleService. Then it gives the finished RoleService to your controller..
You write one line of code. Laravel does the heavy lifting.
The Benefits are clear:
Write less code: You declare it once in the constructor..
Reuse: The service is available in every method in that file (
index,store,update)..Easy Updates: If the service changes, your controller does not care. It just asks for the service, and Laravel figures out how to build it..
Summary Table
| Feature | use App\Class; | __construct(Class $var) |
| What it does | Imports a namespace (Shortcut). | Injects the actual object (Service). |
| Analogy | Looking up a phone number. | Hiring someone to do the job. |
| Creates Object? | No. | Yes, automatically. |
| Logic | None. | fully resolves dependencies. |
Recommended Resources
To truly master this, you should read more about the underlying principles. This is not just a Laravel thing. It is a software engineering standard.
Check the official docs to see how the container resolves classes.
Learn about PSR standards that guide how modern PHP is written.
Dependency Injection is the "D" in SOLID.
The Final Verdict
The use statement simply tells PHP where the class lives. The __construct method tells Laravel to bring that class to life..
By switching from manual creation (new Class) to Dependency Injection, you make your code cleaner, testable, and professional. You stop fighting your code and start letting the framework work for you.
Do you want to see how to refactor your controllers to use this pattern right now? Start by looking at your constructors. If you see new ClassName() anywhere in your code, you have found your next task.
Be the first to show love! ๐
Start something amazing - your support inspires creators!