Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Controllers  ›  Capstone Project

Single-Action Controllers

Single-action controllers 15 minA single-action controller has only an __invoke method, so a route can point at the class itself, which suits one-off actions that do not fit the seven resource methods.

Single-Action Controllers

A member hands a book back. Lendly must mark the loan returned, record the date and make the book available again. Is that store? update? destroy? It is none of them cleanly. It is its own action with its own meaning. Laravel's answer is a controller that does exactly one thing.

The rule

One job, one class, one __invoke method.

Generate it with --invokable:

php artisan make:controller ReturnLoanController --invokable

The class has a single method, __invoke, which PHP calls when an object is used like a function:

namespace App\Http\Controllers;

use App\Models\Loan;

class ReturnLoanController extends Controller
{
    public function __invoke(Loan $loan)
    {
        $loan->update(['returned_at' => now()]);

        return to_route('loans.index');
    }
}

The route points at the class alone, with no method name:

Route::post('/loans/{loan}/return', ReturnLoanController::class)
    ->name('loans.return');

The button is an ordinary form:

<form method="POST" action="{{ route('loans.return', $loan) }}">
    @csrf
    <button>Return book</button>
</form>

Everything from this section still applies: route model binding hands __invoke the Loan, the name lets templates link to it, and the route can sit inside a group for its middleware.

When to reach for one:

  • an action that is not plain create, read, update or delete, such as returning, renewing, approving or exporting
  • a page with a lot of logic that would make a resource controller bloated

The shortcut

Before adding a method to a resource controller, ask "is this one of the seven?" If it is, it goes in the resource controller. If you have to explain it with a verb of its own, such as "return", "renew" or "publish", give it its own invokable class and name the class after that verb.

Placing Lendly's loan actionsStep 1 of 4
  1. List a member's loans

    One of the seven: LoanController@index.

The trap is writing [ReturnLoanController::class, '__invoke'] or 'return' in the route. Pass the class name alone, and Laravel calls __invoke for you.

Drills

Answer fast — trust the rule.

quick drill

Which flag makes make:controller generate a single-action controller?

quick drill

How does a route point at ReturnLoanController?

quick drill

Which Lendly action best fits a single-action controller?

quick drill

In __invoke(Loan $loan) for /loans/{loan}/return, what fills $loan?

quick drill

Why is the return button a POST form rather than a plain link?

Remember

  • One job, one class, one __invoke method.
  • "Is this one of the seven?" If not, name an invokable class after the verb.
  • Trap: route to the class alone, not to __invoke by name.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainReturning a book

Lendly needs a 'return this book' button. Explain why it does not fit neatly into the seven resource methods, then design it as a single-action controller: the Artisan command, the method, the route and how the form reaches it.