A package to help you clean up your controllers in laravel

Overview

πŸ”₯ Laravel Terminator πŸ”₯

πŸ’Ž "Tell, don't ask principle" for your laravel controllers

What this package is good for ?

Short answer : This package helps you clean up your controller code in a way that you have never seen before

Latest Stable Version Build Status Quality Score License Total Downloads

**Made with ❀️ for every laravel "Clean Coder"**

Installation:

composer require imanghafoori/laravel-terminator

No need to add any service providers.

Compatibility:

  • Laravel +5.1 and above
  • Php 7.0 and above

When to use it?

Code smell: πŸ‘ƒ

  • When you see that you have an endpoint from which you have to send back more than one type of response... Then this package is going to help you a lot.

Example:

Consider a typical login endpoint, It may return 5 type of responses in different cases:

  • 1- User is already logged in, so redirect.
  • 2- Successfull login
  • 3- Invalid credentials error
  • 4- Incorrect credentials error
  • 5- Too many login attempts error

The fact that MVC frameworks force us to "return a response" from controllers prevents us from simplify controllers beyond a certain point. So we decide to break that jail and bring ourselves freedom.

The idea is : Any class in the application should be able to send back a response.

Remember:

Controllers Are Controllers, They Are Not Responders !!!

Controllers, "control" the execution flow of your code, and send commands to other objects, telling them what to do. Their responsibility is not returning a "response" back to the client. And this is the philosophy of terminator package.

Consider the code below:

// BAD code : Too many conditions
// BAD code : In a single method
// BAD code : (@_@)   (?_?)
// (It is not that bad, since it is a simplified example)
class AuthController {
  public function login(Request $request)
  {
           
           $validator = Validator::make($request->all(), [
              'email' => 'required|max:255||string',
              'password' => 'required|confirmed||string',
          ]);
          
          if ($validator->fails()) {
              return redirect('/some-where')->withErrors($validator)->withInput(); // return response 1
          }
          
         
          // 2 - throttle Attempts
          if ($this->hasTooManyLoginAttempts($request)) {
              $this->fireLockoutEvent($request);
              return $this->sendLockoutResponse($request);   // return response 2
          }
        
         
          // 3 - handle valid Credentials
          if ($this->attemptLogin($request)) {
              return $this->sendLoginResponse($request);   // return response 3
          }
        

          // 4 - handle invalid Credentials
          $this->incrementLoginAttempts($request);
          return $this->sendFailedLoginResponse($request); // return response 4
          
          
          //These if blocks can not be extracted out. Can they ?
  }
}

Problem :

With the current approach, this is as much as we can refactor at best. Why? because the controllers are asking for response, they are not telling what to do.

We do not want many if conditions all within a single method, it makes the method hard to understand and reason about.

// Good code
// Good code
// Good code

class LoginController
{
    public function Login(Request $request)
    {
        // Here we are telling what to do (not asking them)
        // No response, just commands, Nice ???
        
        $this->validateRequest();          // 1
        $this->throttleAttempts();         // 2
        $this->handleValidCredentials();   // 3 
        $this->handleInvalidCredentials(); // 4
        
    }
    
    // private functions may sit here
    
    ...
    
}

Note:

Using "respondWith()" does not prevent the normal execution flow of the framework to be interrupted. All the middlewares and other normal termination process of the laravel will happen as normal. So it is production ready! 🐬

Refactoring Steps: πŸ”¨

1 - First, you should eliminate "return" statements in your controllers like this:

use \ImanGhafoori\Terminator\Facades\Responder;

class AuthController {
    public function login(Request $request)
    {
           // 1 - Validate Request
           $validator = Validator::make($request->all(), [
              'email' => 'required|max:255||string',
              'password' => 'required|confirmed||string',
          ]);
          
          if ($validator->fails()) {
               $response = redirect('/some-where')->withErrors($validator)->withInput();
               respondWith($response);  // <-- look here
          }
          
         
          // 2 - throttle Attempts
          if ($this->hasTooManyLoginAttempts($request)) {
              $this->fireLockoutEvent($request);
              $response = $this->sendLockoutResponse($request);
              respondWith($response); // <-- look here "no return !!!"
          }
          
         
          // 3 - handle valid Credentials
          if ($this->attemptLogin($request)) {
               $response = $this->sendLoginResponse($request);
               respondWith($response);  // <-- look here  "no return !!!"
          }
          

          // 4 - handle invalid Credentials
          $this->incrementLoginAttempts($request);
          $response = $this->sendFailedLoginResponse($request) 
         
          respondWith($response);  // <-- look here "no return !!!"
    }
}

Do you see how "return" keyword is now turned into regular function calls ?!

2 - Now that we have got rid of return statements,then the rest is easy, It is now possible to extract each if block into a method like below:

class LoginController
{
    public function Login(Request $request)
    {
        $this->validateRequest();         
        $this->throttleAttempts();       
        $this->handleValidCredentials();  
        $this->handleInvalidCredentials(); 
        
    }
    ...
}

Terminator API

All this package exposes for you is 2 global helper functions and 1 Facade:

  • respondWith()
  • sendAndTerminate()
  • \ImanGhafoori\Terminator\TerminatorFacade::sendAndTerminate()
$response = response()->json($someData);

respondWith($response);

// or 
respondWith()->json($someData);


// or an alias function for 'respondWith()' is 'sendAndTerminate':

sendAndTerminate($response);


// or use facade :
\ImanGhafoori\Terminator\TerminatorFacade::sendAndTerminate($response);

In fact sendAndTerminate() ( or it's alias "respondWith" ) function can accept anything you normally return from a typical controller.

About Testibility:

Let me mention that the "sendAndTerminate or respondWith" helper functions (like other laravel helper functions) can be easily mocked out and does not affect the testibility at all.

// Sample Mock
TerminatorFacade::shouldRecieve('sendAndTerminate')->once()->with($someResponse)->andReturn(true);

In fact they make your application for testable, because your tests do not fail if you change the shape of your response.

How The Magic Is Even Possible, Dude ?!

You may wonder how this magic is working behind the scenes. In short it uses nothing more than a standard laravel "renderable exception".

We highly encourage you to take a look at the simple source code of the package to find out what's going on there. It is only a few lines of code.

More from the author:

Laravel Hey Man

πŸ’Ž It allows to write expressive code to authorize, validate and authenticate.


Laravel Any Pass

πŸ’Ž A minimal package that helps you login with any password on local environments.


Laravel Widgetize

πŸ’Ž A minimal yet powerful package to give a better structure and caching opportunity for your laravel apps.


Laravel Master Pass

πŸ’Ž A simple package that lets you easily impersonate your users.

Eloquent Relativity

πŸ’Ž It allows you to decouple your eloquent models to reach a modular structure


⭐️ Your Stars Make Us Do More ⭐️

As always if you found this package useful and you want to encourage us to maintain and work on it, Please press the star button to declare your willing.


🍌 Reward me a banana 🍌

so that I will have energy to start the next package for you.

  • Dodge Coin: DJEZr6GJ4Vx37LGF3zSng711AFZzmJTouN
  • LiteCoin: ltc1q82gnjkend684c5hvprg95fnja0ktjdfrhcu4c4
  • BitCoin: bc1q53dys3jkv0h4vhl88yqhqzyujvk35x8wad7uf9
  • Ripple: rJwrb2v1TR6rAHRWwcYvNZxjDN2bYpYXhZ
  • Etherium: 0xa4898246820bbC8f677A97C2B73e6DBB9510151e

I believe in standardizing automobiles. I do not believe in standardizing human beings.

"Albert Einstein"

You might also like...
A rate limiter for Laravel
A rate limiter for Laravel

Laravel Throttle Laravel Throttle was created by, and is maintained by Graham Campbell, and is a rate limiter for Laravel. Feel free to check out the

YCOM Impersonate. Login as selected YCOM user πŸ§™β€β™‚οΈin frontend.

YCOM Impersonate Login as selected YCOM user in frontend. Features: Backend users with admin rights or YCOM[] rights, can be automatically logged in v

Data providers encapsulate logic for Inertia views, keep your controllers clean and simple.

Laravel Data Providers for Inertia.js Data providers encapsulate logic for Inertia views, keep your controllers clean and simple. Installation We assu

A Cli tool to save you time, and gives you the power to scaffold all of your models,controllers,commands
A Cli tool to save you time, and gives you the power to scaffold all of your models,controllers,commands

A Cli tool to save you time, and gives you the power to scaffold all of your models,controllers,commands... at once Installation You can install the p

laravel package help you to implement geographical calculation, with several algorithms that help you deal with coordinates and distances.
laravel package help you to implement geographical calculation, with several algorithms that help you deal with coordinates and distances.

Geographical Calculator Geographical Calculator was developed for laravel 5.8+ to help you to implement geographical calculation, with With several al

Documentation on clean coding and demonstration of studied clean coding principals with PHP.

practice-php-clean-code Documentation on clean coding and demonstration of studied clean coding principals with PHP. The document contained in this re

Remindle is here to help you remember. Remember everything you want, by the means you prefer, in the frequency you like

platform Personal reminders About Remindle Remindle is a platform which helps you to remember all important events. You can set the means you’d like t

Create your routes using attributes in your controllers

Create your routes using attributes in your controllers

CodeIgniter4 Attribute Routes. You can set Routes in Controllers as PHP8 Attributes.

CodeIgniter4 Attribute Routes This package generates a Routes File from the Attribute Routes in your Controllers. You can set routes in your Controlle

Package to easily test crudable controllers for Laravel based API

Laravel Crudable Test This package is very usefull to easily test crudable controllers. Installation You can install package via composer. Add reposit

Testbench Component is the de-facto package that has been designed to help you write tests for your Laravel package

Laravel Testing Helper for Packages Development Testbench Component is the de-facto package that has been designed to help you write tests for your La

Demo of how you can run your Laravel app with Docker Compose. Look at docker-compose.yml and the docker folder. The rest is just a clean Laravel + Horizon install.

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

Create secure controllers with routing system in Laravel.
Create secure controllers with routing system in Laravel.

Power Gates A simple Laravel application for testing Gates and Policy. Using laravel middlewares, routes and gates to create an Authenticated website.

Backend controllers and scaffolding for Laravel authentication.

Introduction Laravel Fortify is a frontend agnostic authentication backend for Laravel. Fortify powers the registration, authentication, and two-facto

Laravel magical helpers such as Controllers / Requests / Models

Laravel Magic provides Abstract Controller, Model, generic Request, Traits, Exceptions and various middlewares in order to generate very easily and quickly API resources from scratch.

Provides a clean and simple way to configure the WordPress-bundled PHPMailer library, allowing you to quickly get started sending mail through a local or cloud based service of your choice

WP PHPMailer provides a clean and simple way to configure the WordPress-bundled PHPMailer library, allowing you to quickly get started sending mail through a local or cloud based service of your choice.

This small POC aims to show how Symfony is able, natively without modifications, to use subdirectories for Entities, Repositories, controllers, views…

POC - Using Sub Directories in a Symfony Project This small POC aims to show how Symfony is able, natively without modifications, to use subdirectorie

Sistema de Rotas com Controllers e Middlewares

Sistema de Rotas com Controllers e Middlewares

Comments
  • Not installed for Laravel 6.0

    Not installed for Laravel 6.0

     Problem 1
        - laravel/framework 5.0.x-dev requires ext-mcrypt * -> the requested PHP extension mcrypt is missing from your system.
        - Conclusion: don't install imanghafoori/laravel-terminator v1.3.2
        - Conclusion: don't install imanghafoori/laravel-terminator v1.3.1
        - Conclusion: remove laravel/framework v6.0.3
        - Installation request for imanghafoori/laravel-terminator ^1.3 -> satisfiable by imanghafoori/laravel-terminator[v1.03, v1.3.1, v1.3.2].
        - Conclusion: don't install laravel/framework v6.0.3
        - imanghafoori/laravel-terminator v1.03 requires laravel/framework 5.* -> satisfiable by laravel/framework[5.0.x-dev, 5.1.x-dev, 5.2.x-dev, 5.3.x-dev, 5.4.x-dev, 5.5.x-dev, 5.6.x-dev, 5.7.x-dev, 5.8
    .x-dev].
        - Can only install one of: laravel/framework[5.8.x-dev, v6.0.3].
        - Can only install one of: laravel/framework[5.1.x-dev, v6.0.3].
        - Can only install one of: laravel/framework[5.2.x-dev, v6.0.3].
        - Can only install one of: laravel/framework[5.3.x-dev, v6.0.3].
        - Can only install one of: laravel/framework[5.4.x-dev, v6.0.3].
        - Can only install one of: laravel/framework[5.5.x-dev, v6.0.3].
        - Can only install one of: laravel/framework[5.6.x-dev, v6.0.3].
        - Can only install one of: laravel/framework[5.7.x-dev, v6.0.3].
        - Installation request for laravel/framework (locked at v6.0.3, required as 6.0.*) -> satisfiable by laravel/framework[v6.0.3].
    
    
    opened by Claud 4
  • Illuminate\Http\Exceptions\HttpResponseException::__construct() must be an instance of Symfony\Component\HttpFoundation\Response, bool given

    Illuminate\Http\Exceptions\HttpResponseException::__construct() must be an instance of Symfony\Component\HttpFoundation\Response, bool given

    hi , when return false with respondWith like respondWith(false); get FatalThrowableError with this message

    Argument 1 passed to Illuminate\Http\Exceptions\HttpResponseException::__construct() must be an instance of Symfony\Component\HttpFoundation\Response, bool given, called in "Local Path"\vendor\imanghafoori\laravel-terminator\src\Terminator.php on line 14

    opened by Mthreat 1
Releases(v1.3.5)
Owner
Iman
Coding is sport, it is art, it is science.
Iman
A collection of tools to help with PHP command line utilities

PHP Command Line Tools A collection of functions and classes to assist with command line development. Requirements PHP >= 5.3 Suggested PHP extensions

WP-CLI 651 Dec 21, 2022
Deptrac is a static code analysis tool for PHP that helps you communicate, visualize and enforce architectural decisions in your projects

Deptrac is a static code analysis tool for PHP that helps you communicate, visualize and enforce architectural decisions in your projects. You can freely define your architectural layers over classes and which rules should apply to them.

QOSSMIC GmbH 2.2k Dec 30, 2022
Feel free to create new file, don't hesitate to pull your code, the most important thing is that the file name here must match your nickname so that file does not conflict with other people.

PHP-Projects hacktoberfest Contributing Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to cha

Firmansyah Helmi Kurniawan 43 Nov 28, 2022
A PocketMine-MP plugin which let's you whitelist specific commands on specific worlds.

LevelLimiter A PocketMine-MP plugin which let's you whitelist specific commands on specific worlds. Config.yml Set up the commands and the whitelisted

MCA7 7 Aug 6, 2022
All In 1 Spam Tool For Termux Users Subscribe Us (Noob Hackers) some shit heads are trying to abuse this script so don't worry about them ...let them hallucinate ...but you are free to use this script

ABOUT TOOL : SPAMX is a all in one Bombing+Spam tool from this tool you can send anonymous messages to your target without showing your real number an

N17R0 449 Jan 7, 2023
Automagically generate UML diagrams of your Laravel code.

Laravel UML Diagram Generator Automagically generate UML diagrams of your Laravel code. Installation To install LTU via composer, run the command: com

Andy Abi Haidar 93 Jan 1, 2023
PHP Static Analysis Tool - discover bugs in your code without running it!

PHPStan - PHP Static Analysis Tool PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs even b

PHPStan 11.6k Dec 30, 2022
Rector upgrades rules for Laravel

Rector Rules for Laravel See available Laravel rules Install This package is already part of rector/rector package, so it works out of the box. All yo

Rector 185 Dec 30, 2022
A fake mailer for Laravel Applications for testing mail.

MailThief MailThief is a fake mailer for Laravel applications (5.0+) that makes it easy to test mail without actually sending any emails. Note: Due to

Tighten 688 Nov 29, 2022
A toolbar for Laravel Telescope, based on the Symfony Web Profiler.

Laravel Telescope Toolbar Extends Laravel Telescope to show a powerful Toolbar See https://github.com/laravel/telescope Install First install Telescop

Fruitcake 733 Dec 30, 2022