Skip to main content

Single Responsibility: Move Controller Code to Trait

Premium
5 min read

In this lesson, we will discuss SOLID code with the Single Responsibility Principle and clearer method names.


The Problem: Base Controller and Trait

First, the project has a "Base" API Controller with a few methods that can be reused in other Controllers. Some of them are for typical API responses.

app/Http/Controllers/Api/V1/ApiController.php

class ApiController extends Controller
 
// ...
 
public function notAuthorized(string $message = 'You are not authorized.')
{
return $this->error($message, Response::HTTP_UNAUTHORIZED);
}
 
public function notFound(string $message = 'Not Found.')
{
return $this->error($message, Response::HTTP_NOT_FOUND);
}
 
public function unexpectedError(string $message = 'An unexpected error occurred.')
{
return $this->error($message, Response::HTTP_INTERNAL_SERVER_ERROR);
}
 
public function dbError(string $message = 'Database error.')
{
return $this->error($message, Response::HTTP_INTERNAL_SERVER_ERROR);
}

But wait, what is that $this->error()?

Then I noticed a trait for API Responses:

app/Http/Controllers/Api/V1/ApiController.php

use App\Traits\V1\ApiResponses;
 
class ApiController extends Controller
{
use ApiResponses;

Inside that Trait, we have more "general" methods for API responses:

app/Traits/V1/ApiResponses.php:

trait ApiResponses
{
protected function ok(string $message, array $data = [])
{
return $this->success($message, $data, 200);
}
 
protected function success(string $message, array $data = [], int $statusCode = 200)
{
return response()->json([
'data' => $data,
'message' => $message,
'status' => $statusCode,
], $statusCode);
}
 
protected function error($message, $statusCode)
{
return response()->json(['errors' => $message, 'status' => $statusCode], $statusCode);
}
}

And I had a few questions here:

  1. Traits are usually used when you would use them multiple times in different places. I am unsure if another BaseController is planned: maybe in V2 much later? So why trait?
  2. Okay, if you want to use this Trait, then why mix methods in the Controller and in that Trait? According to SRP, they must be in one place.

So, I decided to...

The Full Lesson is Only for Premium Members

Want to access all of our courses? (30 h 09 min)

You also get:

55 courses
Premium tutorials
Access to repositories
Private Discord
Get Premium for $129/year or $29/month

Already a member? Login here

Comments & Discussion

No comments yet…

We'd Love Your Feedback

Tell us what you like or what we can improve

Feel free to share anything you like or dislike about this page or the platform in general.