Restructuring a Laravel controller using Services & Action Classes
Tags: opensource, php, laravelframework, laravel
Published: 2022-06-11 14:22:56

---
title: Restructuring a Laravel controller using Services & Action Classes
published: true
date: 2022-06-02 20:31:47 UTC
tags: opensource,php,laravelframework,laravel
canonical_url: https://blog.devgenius.io/restructuring-a-laravel-controller-using-services-action-classes-288b802122b5
---

#### Laravel Refactoring — Laravel creates an admin panel from scratch — Part 11

![Restructuring a Laravel controller using Services & Action Classes](https://cdn-images-1.medium.com/max/1024/0*gJl0MNlGKL18Yqi8)
_Photo by GR Stocks on Unsplash_

In the [previous part](https://dev.to/balajidharma/restructuring-a-laravel-controller-using-form-request-validation-3k77-temp-slug-5067915), we moved the UserController store method validation to Form Request. In this part, we going to explore and use the new trending Actions and Services Classes.

We going to cover the below topic in the blog

- Laravel project structure
- Controller Refactoring
- Service Class
- — What is Service Class
- — Implement Service Class
- Action Class
- — Implement Action Class
- Advantages of Services & Action Classes
- Disadvantages of Services & Action Classes
- Conclusion

### Laravel project structure

The Laravel does not restrict your project structure also they do not suggest any project structure. So, you have the freedom to choose your project structure.

> Laravel gives you the flexibility to choose the structure yourself

We will explore both Services & Action Classes and we use these classes in our [Laravel basic admin panel](https://github.com/balajidharma/basic-laravel-admin-panel).

### Controller Refactoring

The serController the store function does the below 3 actions.

```
public function store(StoreUserRequest $request)
{
    // 1.Create a user
    $user = User::create([
        'name' => $request->name,
        'email' => $request->email,
        'password' => Hash::make($request->password),
    ]);

    // 2.Assign role to user
    if(! empty($request->roles)) {
        $user->assignRole($request->roles);
    }

    // 3.Redirect with message
    return redirect()->route('user.index')
                    ->with('message','User created successfully.');
}
```

To further refactoring, we can move the logic to another class method. This new class is called Services & Action Classes. We will see them one by one.

### Services Class

We decided to move the logic to another class. The [_Laravel best practices_](https://github.com/alexeymezenin/laravel-best-practices/#business-logic-should-be-in-service-class) are suggested to move business logic from controllers to service classes due to the [_Single-responsibility principle_](https://en.wikipedia.org/wiki/Single-responsibility_principle) _(SRP)._ The Service class is just a common PHP class to put all our logic.

#### What is Service Class

A service is a very simple class and it is not extended with any class. So, it is just a standalone PHP class.

We going to create a new app/Services/Admin/UserService.phpservice class with the createUser method. This is a custom PHP class in Laravel, so no artisan command. We need to create manually.

#### Implement Service Class

app/Services/Admin/UserService.php

```
<?php
namespace App\Services\Admin;
 
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
 
class UserService
{
    public function createUser(Request $request): User
    {
        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
        ]);

        if(! empty($request->roles)) {
            $user->assignRole($request->roles);
        }

        return $user;
    }
}
```

Then, in the UserController call this method. The [Automatic Injection](https://laravel.com/docs/9.x/container#automatic-injection) you may type-hint the dependency in the controller.

app/Http/Controllers/Admin/UserController.php

```
use App\Services\Admin\UserService;

public function store(StoreUserRequest $request, UserService $userService)
{
    $userService->createUser($request);

    return redirect()->route('user.index')
                    ->with('message','User created successfully.');
}
```

We can do some more refactoring on UserService Class by moving the user role saving to the new method.

app/Services/Admin/UserService.php

```
class UserService
{
    public function createUser(Request $request): User
    {
        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
        ]);

        return $user;
    }

    public function assignRole(Request $request, User $user): void
    {
        $roles = $request->roles ?? [];
        $user->assignRole($roles);
    }
}
```

app/Http/Controllers/Admin/UserController.php

```
public function store(StoreUserRequest $request, UserService $userService)
{
    $user = $userService->createUser($request);

    $userService->assignRole($request, $user);

    return redirect()->route('user.index')
                    ->with('message','User created successfully.');
}
```

Now we implemented the Service class. We will discuss the benefit at the end of the blog.

[Click here](https://laravelexamples.com/tag/services) to view example for service classes used on Laravel

### Action Class

In the Laravel community, the concept of Action classes got very popular in recent years. An action is a very simple PHP class similar to the Service class. But Action class only has one public method execute or handle Else you could name that method whatever you want.

#### Implement Action Class

We going to create a new app/Actions/Admin/User/CreateUser.phpAction class with the singlehandle method.

app/Actions/Admin/User/CreateUser.php

```
<?php
namespace App\Actions\Admin\User;
 
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
 
class CreateUser
{
    public function handle(Request $request): User
    {
        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
        ]);

        $roles = $request->roles ?? [];
        $user->assignRole($roles);

        return $user;
    }
}
```

Now call this handle method on UserController. The [method injection](https://laravel.com/docs/9.x/container#automatic-injection) to resolve CreateUser.

app/Http/Controllers/Admin/UserController.php

```
public function store(StoreUserRequest $request, CreateUser $createUser)
{
    $createUser->handle($request);

    return redirect()->route('user.index')
                    ->with('message','User created successfully.');
}
```

The biggest advantage of this Action class we don’t worry about the function name. Because it should always single function like handle

### Advantages of Services & Action Classes

- **Code reusability** : We can call the method on the Artisan command and also easy to call other controllers.
- **Single-responsibility principle (SRP)**: Achieved SRP by using Services & Action Classes
- **Avoid Conflict** : Easy to manage code for the larger applications with a large development team.

### Disadvantages of Services & Action Classes

- **Too many classes** : We need to create too many classes for single functionality
- **Small Application** : Not recommended for smaller applications

### Conclusion

As said earlier, The Laravel gives you the flexibility to choose the structure yourself. The Services and Action classes are one of the structure methods. It should be recommended for large-scale applications to avoid conflict and do faster releases.

For the [Laravel Basic Admin Panel](https://github.com/balajidharma/basic-laravel-admin-panel), I am going with Actions classes.

The Laravel admin panel is available on [https://github.com/balajidharma/basic-laravel-admin-panel](https://github.com/balajidharma/basic-laravel-admin-panel). Install the admin panel and share your feedback.

Thank you for reading.

Stay tuned for more!

_Follow me at_ [**_balajidharma.medium.com_**](https://balajidharma.medium.com/).

Previous part — Part 10: [Restructuring a Laravel controller using Form Request Validation](https://dev.to/balajidharma/restructuring-a-laravel-controller-using-form-request-validation-3k77-temp-slug-5067915)

Next part — Part 12: [Create Reusable Blade Components in Laravel](https://blog.devgenius.io/create-reusable-blade-components-in-laravel-5607d8f306a6)


* * *