After and Before Hooks with Laravel Controller

After and Before Hooks with Laravel Controller

Have you ever encountered a situation where you want to perform an action before or after certain controller methods, perhaps to avoid code duplication, writing an event listener, or creating va…


This content originally appeared on DEV Community and was authored by Claude Fassinou

After and Before Hooks with Laravel Controller

Have you ever encountered a situation where you want to perform an action before or after certain controller methods, perhaps to avoid code duplication, writing an event listener, or creating validation files? You want to keep things simple but move faster. Here's how you can solve this problem. Unfortunately, without an optimized approach, these repetitive tasks can lead to code duplication, making your application harder to maintain.

Do you want to avoid duplicating code or repeatedly writing listeners? Are you looking for a simple and fast solution?

In this article, we will solve this issue using a powerful and flexible approach: controller hooks in Laravel. With this technique, you can automate cross-cutting actions without touching the code of your controller methods. It’s an elegant solution to improve the clarity and maintainability of your code.

The Problem: Code Duplication and Lack of Flexibility

Let’s take a classic example. Suppose you have a controller with several methods that require similar operations, like initializing a service or formatting responses. The following code illustrates this repetition:

class ExampleController extends Controller
{
    private $someService;

    public function __construct(SomeService $someService)
    {
        $this->someService = $someService;
    }

    public function methodA(Request $request)
    {
        $this->someService->init($request->some_id)->withModel();
        // Specific logic for methodA
        $result = // ...
        return $this->formatResponse($result);
    }

    public function methodB(Request $request)
    {
        $this->someService->init($request->some_id)->withModel();
        // Specific logic for methodB
        $result = // ...
        return $this->formatResponse($result);
    }

    private function formatResponse($data)
    {
        return response()->json(['success' => true, 'data' => $data]);
    }
}

Problems:

  1. Code duplication: The service initialization is duplicated in each method.
  2. Clutter: The response formatting is also duplicated, making long-term maintenance difficult.
  3. Lack of flexibility: Adding new cross-cutting features, such as logging or error handling, requires modifying each method.

The Solution: Using Hooks in Controllers

With controller hooks, you can centralize these operations and apply them automatically before or after the execution of the relevant methods. Here’s how to refactor the previous example using this approach.

Refactoring with Hooks

use LaravelHooks\Traits\HasControllerHooks;

class ExampleController extends Controller
{
    use HasControllerHooks;

    private $someService;

    public function __construct(SomeService $someService)
    {
        $this->someService = $someService;
    }

    public function methodA(Request $request)
    {
        // Specific logic for methodA
        return // ...
    }

    public function methodB(Request $request)
    {
        // Specific logic for methodB
        return // ...
    }

    public function useHooks()
    {
        $this->beforeCalling(['methodA', 'methodB'], function ($request, ...$params) {
            $this->someService->init($request->some_id)->withModel();
        });

        $this->afterCalling(['methodA', 'methodB'], function ($result) {
            return response()->json(['success' => true, 'data' => $result]);
        });
    }
}

Benefits of Using Hooks

  1. Cleaner and more concise code: Each method focuses only on business logic. Repetitive actions are handled elsewhere.
  2. Centralized initialization: No need to duplicate service initialization in every method.
  3. Consistent response formatting: Formatting is applied uniformly without duplication.
  4. Easier to add new features: Hooks allow you to quickly add new functionalities like logging or error handling without modifying existing methods.

Practical Use Case: Payment Management

Let’s take a concrete use case to illustrate this approach. Imagine a payment management system where you need to check security, initiate services, and format responses. Here’s how to use hooks to make the code cleaner and more maintainable:

use LaravelHooks\Traits\HasControllerHooks;

class PaymentController extends Controller
{
    use HasControllerHooks;

    private $paymentService;

    public function __construct(PaymentService $paymentService)
    {
        $this->paymentService = $paymentService;
    }

    public function store(Request $request)
    {
        return $this->paymentService->createPayment($request->all());
    }

    public function verify(Request $request, $paymentId)
    {
        return $this->paymentService->verifyPayment($paymentId);
    }

    public function checkStatus(Request $request, $paymentId)
    {
        return $this->paymentService->checkPaymentStatus($paymentId);
    }

    public function useHooks()
    {
        $this->beforeCalling(['store', 'verify', 'checkStatus'], function ($request, ...$params) {
            $this->paymentService->init($request->payment_id);
            Log::info("Payment operation initiated", ['method' => $this->currentMethod, 'user_id' => auth()->id()]);

            // Security check
            if (!$this->securityService->verifyUserAllowed(auth()->user(), $request->payment_id)) {
                throw new UnauthorizedPaymentException("User not authorized for this payment operation");
            }
        });

        $this->afterCalling(['store', 'verify', 'checkStatus'], function ($result) {
            return response()->json(['success' => true, 'data' => $result]);
        });

        $this->addErrorHandler(PaymentException::class, function ($e) {
            return response()->json(['success' => false, 'error' => $e->getMessage()], 400);
        });
    }
}

What Hooks Bring to the Table:

  1. Simplified service initialization: No need to write initialization code in every method.
  2. Automatic logging: Each payment operation is logged without extra effort.
  3. Centralized security checks: Security is handled centrally before each payment-related method.
  4. Simplified error handling: A clear and centralized approach to handling specific exceptions.

Source

laravel-hooks


This content originally appeared on DEV Community and was authored by Claude Fassinou


Print Share Comment Cite Upload Translate Updates
APA

Claude Fassinou | Sciencx (2024-09-20T17:22:32+00:00) After and Before Hooks with Laravel Controller. Retrieved from https://www.scien.cx/2024/09/20/after-and-before-hooks-with-laravel-controller/

MLA
" » After and Before Hooks with Laravel Controller." Claude Fassinou | Sciencx - Friday September 20, 2024, https://www.scien.cx/2024/09/20/after-and-before-hooks-with-laravel-controller/
HARVARD
Claude Fassinou | Sciencx Friday September 20, 2024 » After and Before Hooks with Laravel Controller., viewed ,<https://www.scien.cx/2024/09/20/after-and-before-hooks-with-laravel-controller/>
VANCOUVER
Claude Fassinou | Sciencx - » After and Before Hooks with Laravel Controller. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2024/09/20/after-and-before-hooks-with-laravel-controller/
CHICAGO
" » After and Before Hooks with Laravel Controller." Claude Fassinou | Sciencx - Accessed . https://www.scien.cx/2024/09/20/after-and-before-hooks-with-laravel-controller/
IEEE
" » After and Before Hooks with Laravel Controller." Claude Fassinou | Sciencx [Online]. Available: https://www.scien.cx/2024/09/20/after-and-before-hooks-with-laravel-controller/. [Accessed: ]
rf:citation
» After and Before Hooks with Laravel Controller | Claude Fassinou | Sciencx | https://www.scien.cx/2024/09/20/after-and-before-hooks-with-laravel-controller/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.