Segun Olaiya
Posted on July 2, 2019
We all agree that methods and function should do one thing only. We call this Single Responsibility Principle.
However, the fact that methods should follow SRP does not imply that we should have a controller housing many (almost) independent methods which would result in a very unstructured business logic.
Having a single method controller is a fantastic way of upholding the Single Responsibility Principle. For example, take a look at the controller below
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Plan;
class PlansController extends Controller
{
public function index()
{
//Logic to Get All Plans
}
public function create(Request $request)
{
//Logic to create new Plan
}
public function inviteUser(Request $request)
{
//Logic to invite user to plan
}
}
The first thought that would come to mind is that the inviteUser
method does not belong to this controller. We should have something like InviteUserController
. And that is absolutely what we should do.
From the name of this controller, it is expected to do one thing only - Invite a user to a specific plan.
So we can simply have something like
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class InviteUserController extends Controller
{
public function inviteUser(Request $request)
{
//Logic to invite user to plan
}
}
and we should be done right? - Well how about if this could be done better? - Introducing Magic Method __invoke
:)
PHP has several Magic methods. Magic methods are named with two underscores at the start, which get called automatically when a particular event happens.
The __invoke()
method gets called when the object is called as a function. When you declare it, you say which arguments it should expect. Here's a trivially simple example:
class Human {
public function __invoke() {
echo "Sophisticated creature";
}
}
We can instantiate a Human object, and then just use it like a function:
$victor = new Human();
$victor(); // Sophisticated creature
With this understanding, we can simply rename the inviteUser
method of the InviteUserController
to __invoke
as seen below
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class InviteUserController extends Controller
{
public function __invoke(Request $request)
{
//Logic to invite user to plan
}
}
And in the routes file we would no more use the string literal convention to map a route to this controller instead we add the class like
use App\Http\Controllers\Api;
Route::get('/invite', InviteUserController::class)
Let me know what you think about single method controllers!
Credit: lornajane
PS: This is my first blog post on Dev.to
Posted on July 2, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 28, 2024