>Can you elaborate on this? I'd like to better understand what the
>problem was with constructors that returned values when you upgraded
>from Laravel 9 to Laravel 12.

I can't share real code, because this project is not open source. The
project I maintain uses constructor middleware as follows:

```php
// Laravel 9
class MyController extends Controller
{
    public function __construct()
    {
        $this->middleware(function ($request, $next) {
            if (!Security::isLoggedIn()) {
                return redirect()->route('login');
            }

            return $next($request);
        });
    }
}
```

The goal is to redirect guests to the login page. To prevent
unauthorized actions from being performed.

In Laravel 9, MyController was instantiated before any middleware
was executed. When __construct was executed, Laravel was still
initializing, not much could be done in the __construct function.
Hence the middleware solution.

Then came Laravel 12 and constructor middleware was removed. Also,
middleware is now executed before the controller is instantiated. And
here's where I made my mistake. I removed the $this->middleware() call,
and changed this to:

```php
// Laravel 12 - my mistake, this it totally wrong!
class MyController
{
    public function __construct()
    {
        if (!Security::isLoggedIn()) {
            return redirect()->route('login');
        }

        // Because the return value is pointless, no redirection
        // did find place.
        // The unauthorized user could actually call real controller
        // functions, which could be anything from  showHomepage() to
        // rebootTheSystem() - exaggerated of course.
        //
        // But PHP did not warn me, did not error, did not speak up,
        // did nothing to inform me of my mistake.
    }

    public function showHomepage(Request $request)
    {
    }

    public function rebootTheSystem(Request $request)
    {
    }
}
```

>So, to restate your proposal: you want to disallow returning from
>constructors…but only if invoked when using the `new` keyword?

That is correct.

>So, if you call `$object->__construct()`, there's no error, and you can
>get the return value, but if you do `new Foo()`, you'd get an error?

That is correct.

>The "Make constructors and destructors return void" RFC was voted on and
>declined in 2020. PHP has come a long way since then, and I'm curious
>whether a similar proposal (targeting PHP 9) might pass nowadays. I'd
>certainly consider voting for it. Perhaps in PHP 8.6, we could begin
>emitting a deprecation message for constructors that return values?

Deprecation sounds like a good step forward.

Kind regards,
Mirco Babin

Reply via email to