Single Responsibility Principle in Laravel (S.O.L.I.D)

Awang Trisakti
4 min readFeb 27, 2023

--

Photo by Nathan Queloz on Unsplash

Single Responsibility Principle (SRP) is one of the five SOLID principles of object-oriented programming that states that every module or class should have only one reason to change, meaning that a class should have only one job. The principle helps to make code more maintainable, flexible, and scalable. In this article, we’ll take a closer look at SRP and how it can be implemented in the Laravel PHP framework.

Laravel is a popular open-source PHP framework that makes it easier to develop web applications. The SRP can be applied in Laravel in a number of ways. One way is to create small, focused classes that each have a single responsibility. For example, instead of having a single class that handles authentication, validation, and data storage, you can create separate classes for each of these tasks. This makes it easier to maintain the code and make changes, as each class only has to worry about a single responsibility.

For example, controllers should have only one responsibility, which is to handle user requests and return responses. This means that instead of putting all of the application’s logic in a single controller, you should create other class such as service class for business logic and repository class for database logic. So the controller will only manage the incoming request and will return response as the expected. This makes it easier to maintain the code and make changes. Code below is an example of controller without SRP.

// PostController.php
class PostController
{
/**
* Create post
* @param Request $request
* @return JsonResponse
*/
public function store(Request $request)
{
try {
$data = $request->validate([
'title' => 'required|string',
'body' => 'required|string|max:200',
]);

if (isset($data['image')) {
// Do upload and replace old one if exists
}

$post = Post::create([
'title' => $data['title'],
'body' => $data['body']
]);

// Do other db logic needed

$postResource = [
'id' => $post->id,
'title' => $post->title,
'body' => $post->body,
'created_at' => Carbon::diffForHumans($post->created_at)
];

return response()->json([
'success' => true,
'message' => 'Post created successfully',
'data' =>
], JsonResponse::HTTP_OK);
} catch (\Exception $e) {
return response()->jsom([
'success' => false,
'message' => 'Something went wrong',
'errors' => null
], JsonResponse::HTTP_INTERNAL_SERVER_ERROR);
}
}
}

Here is an example of controller with SRP

// PostController.php
class PostController
{
/**
* Create post
* @param CreatePostRequest $request
* @return JsonResponse
*/
public function store(CreatePostRequest $request)
{
try {
$data = $request->validate();

// Use dependency injection in controller's constructor
$post = $this->service->create($data);
if (!$post instanceof Post) {
throw new Exception();
}

$postResource = new PostResource($post);

return response()->json([
'success' => true,
'message' => 'Post created successfully',
'data' => $postResource
], JsonResponse::HTTP_OK);
} catch (\Exception $e) {
return response()->jsom([
'success' => false,
'message' => 'Something went wrong',
'errors' => null
], JsonResponse::HTTP_INTERNAL_SERVER_ERROR);
}
}
}

// CreatePostRequest.php
class CreatePostRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array<string, mixed>
*/
public function rules()
{
return [
'title' => 'required|string',
'body' => 'required|string|max:200',
];
}

// ....
}

// PostResource.php
class PostResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
return [
'id' => $post->id,
'title' => $post->title,
'body' => $post->body,
'created_at' => Carbon::diffForHumans($post->created_at)
];
}
}
// PostService.php
class PostService {
/**
* Create a new post
* @param array $data
* @return Post|null
*/
public function create(array $data): ?Post
{
try {
// Do some needed business logic
if (isset($data['image')) {
// Do upload and replace old one if exists
}

// Use dependency injection in service's constructor
$post = $this->repository->create($data);

return $post
} catch (\Exception $e) {
return null
}
}
}
// PostRepository.php
class PostRepository {
/**
* Create post
* @param array $data
* @return Post|null
*/
public function create(array $data): ?Post
{
try {
$post = Post::create($data);

// Do other db logic needed

return $post;
} catch(\Exception $e) {
return null;
}
}
}

In the code snippets above we know that PostController is only about to get the request and return the response, validation is done by CreatePostRequest, business logic is done by PostService, database logic is done by PostRepository and generate needed data for response is done by PostResource .

Conclusion
In my opinion Single Responsibility Principle is an important principle that helps to make code more maintainable, flexible, and scalable. By following SRP, you can create small, focused classes that each have a single responsibility, making it easier to maintain the code and make changes without affecting other parts of the application.

That’s all that I can share in this post. I’m not an expert, so please feel free to leave comments for any suggestions or question, I would love to hear any feedbacks from you. Share this post if you found this post useful. See ya

--

--