Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use mixed return type on controller stubs #46166

Merged
merged 2 commits into from Feb 19, 2023
Merged

Use mixed return type on controller stubs #46166

merged 2 commits into from Feb 19, 2023

Conversation

taylorotwell
Copy link
Member

This pull request updates the controller stubs to use a mixed return type to accommodate the various types of return values a controller can return in Laravel.

This allows developers to return anything they want without an error by default, but they can easily tighten up the types as they decide which each controller endpoint will actually return.

@datlechin
Copy link
Contributor

Developers can do it on their own project, I think no need to change to mixed return type in stub

@taylorotwell
Copy link
Member Author

taylorotwell commented Feb 18, 2023

@datlechin I'm well aware they can, the question is whether the default (as it stands currently) should be to error when a developer creates a new controller and tries to return a View. IMO, that's kinda annoying.

I could change the return type to View, but the reality is there are a variety of possible types and primitives a controller can return, and perhaps the default type hint should reflect that reality instead of trying to make some narrow choice that we can't possibly predict.

@yungifez
Copy link

Noob question

Doesn't this kill the whole purpose of return types?

What's the difference between this and no return types at all

And cant we instead do something like this

Response|View etc

@taylorotwell
Copy link
Member Author

taylorotwell commented Feb 18, 2023

@yungifez one could definitely make that argument; however, we have added return types to all other parts of the skeleton so it may feel weird to not have them on controllers at all. Having the mixed type in place at least gives you some text to quickly replace with your own type hint if you wish.

@martinbean
Copy link
Contributor

martinbean commented Feb 18, 2023

@taylorotwell Do views and Eloquent API resources both implement the Responsible interface? Would that suffice as a “looser”—but tighter than mixed—return type?

@taylorotwell
Copy link
Member Author

@martinbean Illuminate\Http\Response itself isn't responsible - neither is View.

@tontonsb
Copy link
Contributor

I agree 100% — the default return type should reflect what the framework is willing to accept here. And it accepts all the views, arrays, strings and everything else.

@yungifez mixed does not include void, it's a bit stricter than nothing. And it's a decent placeholder :)

@LucaRed
Copy link
Contributor

LucaRed commented Feb 18, 2023

I think the return type mixed doesn't add anything of value.

Personally, I always return views for normal web controllers, and responses for API controllers (isn't this the "Laravel way"?). If I had to choose, I'd go with Response|View.

@jonathanmacgregor
Copy link

There could be an opportunity here to direct users to change the return types and educate them at the same time. Adding a note to the head of the stub could point them in the direction of what returns types mean.

They can always be removed in the stubs for users who don't need direction.

@taylorotwell
Copy link
Member Author

taylorotwell commented Feb 18, 2023

@LucaRed I return arrays from controllers pretty frequently. Wouldn't work with that type-hint you suggested.

I personally lean @tontonsb's direction in that the mixed type simply reflects reality. The "reality" is controllers can return a wide variety of things in Laravel - why not make the default type-hint reflect that?

@phpfour
Copy link
Contributor

phpfour commented Feb 18, 2023

Returning mixed is a necessary compromise that we as a community will need to accept. It will allow newcomers to have a smooth experience, while experienced devs can (will) change them anyways for their use cases.

@SaeedDev94
Copy link

SaeedDev94 commented Feb 18, 2023

I don't know if this is possible, but can we extend View by Response class, or can we create an interface for different response types?
I don't like the mixed type 😔

@ashabed
Copy link

ashabed commented Feb 18, 2023

@martinbean Illuminate\Http\Response itself isn't responsible - neither is View.

How about changing that? Make Response and View implement Responsable, as they can both be used for returning from controllers.
Then set the return type to Responsable instead of mixed. Seems like things would be more clear that way.

@joniand
Copy link

joniand commented Feb 18, 2023

Yeah for me too 99% of the times a View type would be more appropriate so having the default being Response is a bit annoying, as much sense as it makes. I think mixed would be better though, this way we also don't need to delete imports etc. if we want to change it...

@martinbean
Copy link
Contributor

@martinbean Illuminate\Http\Response itself isn't responsible - neither is View.

Fair enough. Should the Responsable interface be applied to views in that case if they can, in fact, be used as responses?

@yungifez
Copy link

yungifez commented Feb 18, 2023

I think looking at all these comments mixed is the way to go

@LucaRed
Copy link
Contributor

LucaRed commented Feb 18, 2023

Are there any differences between specifying mixed and not specifying any return type at all? (other than than not allowing void as @tontonsb said)

If there are no differences, we could go with mixed for consistency reasons (and also to make users aware that they can return pretty much anything).

@jorqensen
Copy link

jorqensen commented Feb 18, 2023

Using mixed is like using TypeScript and throwing an any in there, it's simply pointless. I am not a fan of this PR, even though I use Blade and can see the annoyance.

Hopefully a better solution could come out of this, specifically something along of what @martinbean suggests / a common interface as the return type.

@dinhquochan
Copy link
Contributor

dinhquochan commented Feb 18, 2023

I think it should be a Responsable interface and Illuminate\View\View or other stuff should be implemented Responsable interface. mixed type is terrible, like any in TypeScript 🥲

@jrd-lewis
Copy link
Contributor

Food for thought, what about using the Illuminate\Contracts\Support\Renderable interface as the return type?

@iksaku
Copy link
Contributor

iksaku commented Feb 18, 2023

For the sake of further clarification, we can all refer to the Documentation on mixed type.

@LucaRed you’re correct. No return type and mixed mean basically the same from the framework’s perspective that something must be returned from the controller, and as it is Laravel, any value type that is returned from a controller function will properly be transformed into something usable by the framework.

I would argue that to the good initiative to strict-type anything, this is that little exception to the rule where we’re actually typing something for the framework to process initially.

We can always adjust typings as must of us would be already doing, or we can update our projects stubs manually to be more strict.

Talking from a community standpoint, there’s no majority that will use X or Y; every developer will be using their own conventions, and reflecting that from a stubs seems really accurate as @jonathanmacgregor mentioned.

@igorkosteski
Copy link

I think that mixed is bead a idea. What about Illuminate\Contracts\View\View to be default return type,
and if you use --api other then excluding the create and edit, to change the return return type to all the method of the Controller to be Illuminate\Http\Response

@yungifez
Copy link

I think that mixed is bead a idea. What about Illuminate\Contracts\View\View to be default return type, and if you use --api other then excluding the create and edit, to change the return return type to all the method of the Controller to be Illuminate\Http\Response

I don't see what is so bad about returning mixed as a return type.

In my opinion, the framework has functioned without type hints for a long time. You are not accounting for cases like Inertia that does not make use of API controllers and I'm speculating is not of typeIlluminate\Contracts\View\View

Mixed in this case just acts as a decorator to prevent a partially typed application and follow consistent design

@ConsoleTVs
Copy link
Contributor

ConsoleTVs commented Feb 18, 2023

This conversation is leading nowhere. The reality is:

Laravel accepts any return types in controller handlers (strings, arrays, views, Response, etc.). The ideal return type, as for the current API is: mixed.

On another hand, this provides little to no gain at all, makes static typing look useless, and that's no far from the truth. Reality is, that this API is not something I would use for future versions.

Edit: As @taylorotwell mentioned, this discussion is about a good default type for stubs, therefore, given the current API I conclude mixed is a great candidate, still allowing devs to change it.

Perhaps in the future, if there's the need to, we could use mixed internally and leave the surface API fully typed.

There's likely the possibility to do this:

public function foo(): Responsable {
    return response('foo');
}

public function foo(): Responsable {
    return response()->json(['foo' => 'bar']);
}

public function foo(): Responsable {
    return redirect()->route('foo');
}

public function foo(): Responsable {
    return view('foo');
}

public function foo(User $user): Responsable {
    return new UserResource($user);
}

public function foo(): Responsable {
    return UserResource::collection(User::all());
}

The Responsable interface (Illuminate\Contracts\Support\Responsable) is something that should be consistent. Fear not to implement it for types like View or Response. It's common for other languages to do similar stuff. For example in Rust, there's always the From<T> for T (Transforms T to T) implemented implicitly, by just returning itself.

In reality, the response helper will have mixed as it's parameter type, but on the surface we can be sure that the returned type is correct. With good enough internal testing for the helper, we shall be good.

There seems to be no correct answer on this but rather multiple points of view.

@inxilpro
Copy link
Contributor

I personally don't find that return types are very useful on controllers actions, so my first choice would be to just leave them out of that stub (I'm in favor of return types in many other places—but only where they bring value). That said, mixed is a fine option if the consensus is that controller actions should have a return type by default.

@mabdullahsari
Copy link
Contributor

Honestly, since Laravel offers the option to return almost anything from a Controller, it'd be better to remove the type-hints altogether from the Controller stubs. There's just no way to cover every single use case and combination. Trying to do so will result in a Cartesian Explosion.

People can still add a return type of their own if they wish, or just ignore it.

@taylorotwell
Copy link
Member Author

taylorotwell commented Feb 18, 2023

Another option: #46167

Use Responsable after adding it to more classes.

@wlepinski
Copy link

Isn't there a common interface that both Response and View implements that can be used here as the return type?

The main problem I see is that, even with a common interface the only acceptable type here is mixed because the framework accepts also strings and other literals as valid returns from a controller method.

I agree with the sentiment of adding a mixed to solve the problem, it feels like adding an any to a typescript file.

@tweichart
Copy link

tweichart commented Feb 18, 2023

Not to make this too academic but from a SOLID perspective Responsable makes more sense than mixed, where the latter would give more options to return different types of course but then on the other hand too many I feel. Not sure when e.g. I'd want to return an int here, it should not be allowed by means of the return types definition already though, otherwise (as others mentioned already) types don't make much sense here.

Only valid argument against the Interface I've seen here was the array being returned, tbh I didn't even know that this is possible until now and should probably not be the case to start with. In this case I don't feel it's too much of a limitation though, this is not talking about a breaking change for existing classes but only a stub. Meaning, future controllers would be discouraged to return arrays, which again imo wouldn't be the worst idea. Having a typed return defined as an interface would make most sense therefore.

@kevinvanboeckholtz
Copy link
Contributor

make:controller NameController --response, --view, --responsable --mixed, --api

One command to rule them all ~ Lord of the rings

@dillingham
Copy link
Contributor

I think mixed makes the least friction out of the gate. Maybe laravel new can have a flag for changing the controller stubs for smoothing out the customization story. --controller=inertia

@rodrigopedra
Copy link
Contributor

rodrigopedra commented Feb 19, 2023

Note that Illuminate\Http\RedirectResponse does not extend Illuminate\Http\Response, neither does Illuminate\Http\JsonResponse.

Having anything narrower than mixed could:

  • be a pain point when one wants to quickly prototype something and have to remember changing the return type all the time when they are just testing an endpoint returning whatever they want to debug/build it, like strings, array, models, etc.
  • lead to an avalanche of forums requests on how to return things that are already supported. Many users assume the default is somewhat a "best practice".

Having a narrower return type that does not encompass other accepted responses in counterintuitive in both cases.

As others have already said, a controller is fundamentally consumed by the framework, so its methods' return type should satisfy the framework expectations.

IMHO, mixed is the way to go, if having return types on all generated content is the desired goal.

@taylorotwell
Copy link
Member Author

Just going to remove return types on controller method stubs.

@dillingham
Copy link
Contributor

Wouldn't that make phpstan complain?

@taylorotwell taylorotwell merged commit 8f91965 into 10.x Feb 19, 2023
@taylorotwell taylorotwell deleted the controller-types branch February 19, 2023 01:45
@taylorotwell
Copy link
Member Author

@dillingham complain about what? the stubs have no code in them and thus no return type.

@PovilasKorop
Copy link
Contributor

@taylorotwell thanks for taking the time to consider various approaches, and sorry if my tweet caused the headache here.

I agree that removing types is probably the best because historically it worked with almost whatever you would return:

  • view() / response()->view()
  • json
  • collection/model/array - "magically" transformed into json
  • string "It works"
  • Inertia::render()
  • redirect
  • etc.

@madebydanda
Copy link

madebydanda commented Feb 19, 2023

I think the default code should be a good example from where anyone (junior or senior developers) can start from. If we use mixed as a return type we might "teach" juniors that mixed is a correct return type and that they can keep it as it is because it works. They might even think it's a good return type to use in other circumstances.

Sure getting an error when returning a view might be annoying but default stubs shouldn't please everyone or even anyone. We use controllers to handle a "Request", process it and then return a "Response". This for me is the correct way to think.

If the "Response" causes an error I will learn to modify my return type based on my needs and not just use mixed because it works.

Again, I understand the willingness to avoid confusion but I always considered the default code of Laravel as "good practice" to follow or learn from. Using mixed as a return type to avoid errors wouldn't be for me "good practice" or the "right" way to do things.

@rodrigopedra
Copy link
Contributor

@madebydanda on his last commit, Taylor actually removed any return types, you can see on the changes tab.

As the merge title didn't change, it can be misleading.

@madebydanda
Copy link

@rodrigopedra Yes just saw that, well I guess my comment can also apply to the "no return type" solution.

@rodrigopedra
Copy link
Contributor

Well, JsonResponse, and RedirectResponse don't inherit from Response. Neither View does.

I would say in a usual Laravel app those are more common than a plain Response. Should we add those as union types?

Having Response as the default would be misleading in the very same sense some users would assume that is the recommended way to do things.

Also, Laravel strives for DX. Narrowing the return type just because it feels "correct", while the framework can handle many other return types, is neither correct, in the sense it could imply the framework expect you to return a specific data type, but also goes against its philosophy, of moving out the way to let an app code shine, not to make a developer worry about complying to a specification, IMO.

By the way, what is a response? The request object is a wrapper that flats out many PHP inconsistencies, but should a response be wrapped onto a specific class?

Should we move away from model route binding, and have the request object retrieve the route parameters, as a controller method without a request wouldn't feel "correct"?

I understand your concern, but I personally prefer not having a return type suggested than having something like: Response|JsonResponse|RedirectResponse|Responsable|static|iterable|\stdClass, to highlight everything a request can return as a response. That would be more correct, in the sense the framework is ready to handle any of these return types for you.

@madebydanda
Copy link

@rodrigopedra that wasn't really my point. In my opinion it's not an issue to have a specific return type that would throw an error when I return a different type. It "teaches" me something and makes me aware that I either need to update my return type or that I have an actual error in my code.

I would have left everything as it was but I understand the reason why this was modified.

@ConsoleTVs
Copy link
Contributor

I understand your concern, but I personally prefer not having a return type suggested than having something like: Response|JsonResponse|RedirectResponse|Responsable|static|iterable|\stdClass, to highlight everything a request can return as a response. That would be more correct, in the sense the framework is ready to handle any of these return types for you.

That's exactly the purpose of an interface... Illuminate\Contracts\Support\Responsable.

You have to read it as, return me anything that can be turned into a response. However, as I pointed out in some of my comments, the issue will come with primitive types, as you can't implement an interface on them.

@rodrigopedra
Copy link
Contributor

In my opinion it's not an issue to have a specific return type that would throw an error when I return a different type. It "teaches" me something and makes me aware that I either need to update my return type or that I have an actual error in my code.

I got that in the first time. We just happen to have different opinions on this matter.

I don't think it is up to this fundamental part of the framework, to get in front of a developer and try to "teach" them anything.

@rodrigopedra
Copy link
Contributor

rodrigopedra commented Feb 19, 2023

That's exactly the purpose of an interface... Illuminate\Contracts\Support\Responsable.

You have to read it as, return me anything that can be turned into a response. However, as I pointed out in some of my comments, the issue will come with primitive types, as you can't implement an interface on them.

Having to read something differently from what it is written is counter-productive, IMO.

Having an interface on the return type of method is a hint for whoever will consume that method.

And on this particular part of the request/response cycle, a controller method is only consumed by the framework, which can handle many other different types than this interface.

I would agree if Laravel allowed to swap the request dispatcher by something else, like a PSR-7, or PSR-15. In that case, using a contract would enforce compliance with unknown code that could consume that method. That is not the case here, though.

A controller's method is not meant to be reused anywhere else, or consumed by any other part of the framework. It is not code meant to be interoperable, nor code written without knowing who will consume it.

If there is a single consumer, requiring a narrow interface, or contract -- when this consumer does already accept a wider domain of values -- adds little to no value, but unneeded noise and overhead.

I don't want to extend this discussion, as this seems to be a matter of opinion, or self-preference. But what would be the true benefit of enforcing any kind of contract on a controller's method return type, when the only consumer accepts anything from it?

@khru
Copy link

khru commented Feb 19, 2023

I have to say that I am somehow surprised, Laravel has always been a highly opinionated framework, with a very specific way of doing things.

Finally, it has started to standardize things that are logical, like for example, a language based on request, response. End up by returning the obvious, a Response.

I think it is a change that breaks the current way of working, but I see a logical change and, as I mentioned before, consistent with the programming language.

Not only that, it's unnatural to fight against the very language that goes towards typed types.

@ccmiller2018
Copy link

ccmiller2018 commented Feb 19, 2023

so how about a slightly different approach?

  1. the default is to return as is now
  2. if you want it to return an alternative, use a --return option for the stub?

so you might do artisan make:controller --invokable --return=Illuminate\Http\JsonResponse for example?

this feels like it might offer the best of both worlds without compromising the intended purpose of the original method

@rodrigopedra
Copy link
Contributor

rodrigopedra commented Feb 19, 2023

with a very specific way of doing things.

Not sure about that. (see expanded details)
<?php
// routes/web.php

use App\Events\AEvent;
use App\Http\Controllers\AController;
use App\Http\Controllers\AnotherController;
use App\Jobs\AJob;
use App\Models\User;
use App\Notifications\ANotification;
use Auth as AuthAlias;
use Bus as BusAlias;
use DB as DBAlias;
use Event as EventAlias;
use Facades\Illuminate\Http\Request as RequestRealTimeFacade;
use Hash as HashAlias;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Factory;
use Illuminate\Contracts\Bus\Dispatcher as BusDispatcher;
use Illuminate\Contracts\Events\Dispatcher as EventsDispatcher;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Notifications\Dispatcher as NotificationsDispatcher;
use Illuminate\Contracts\Session\Session;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Facades\Queue;
use Illuminate\Support\Facades\Request as RequestFacade;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Session as SessionFacade;
use Illuminate\Support\Str;
use Notification as NotificationAlias;
use Queue as QueueAlias;
use Request as RequestAlias;
use Session as SessionAlias;
use Str as StrAlias;

if (is_file(database_path('database.sqlite'))) {
    User::query()->truncate(); // query() + method
    User::truncate(); // auto delegate to query builder
    DB::query()->from('users')->truncate();
    DBAlias::table('users')->truncate();

    $aUser = User::factory()->createOne([
        'name' => Str::random(),
        'email' => StrAlias::random() . '@example.com',
        'password' => bcrypt('password'),
    ]);

    Auth::login($aUser);

    User::forceCreate([
        'id' => 2,
        'name' => Str::random(),
        'email' => StrAlias::random() . '@example.com',
        'password' => Hash::make('password'),
    ]);
}

Route::get('/foo', AController::class) // with preeciding forward slash
->middleware('web', 'auth'); // middleware as parameter list, auth without guard

// middleware can also be defined on a controller's constructor
// (not shown here)
Route::get('bar', [AnotherController::class, 'method']);

Route::get('baz', AnotherController::class . '@method')
    ->middleware(['web', 'auth:web']) // middleware as array, auth with guard
    ->name('a-name');

Route::get('qux', [
    'prefix' => '/boo',
    'uses' => AnotherController::class . '@method',
    'as' => 'boo.',
    'middleware' => ['auth:web'],
]); // classic, all the others get converted to something like this internally

// helper class, as ijecting Authenticatable
// does not work properly when also injecting User
class AUser extends Model
{
    protected $table = 'users';
    protected $guarded = [];
}

// $router variable is injected on web.php
$router->get('/user/{user}', function (
    Application $app,
    Request $injectedRequest,
    Session $session,
    Authenticatable $authUser,
    BusDispatcher $bus,
    EventsDispatcher $events,
    NotificationsDispatcher $notifications,
    Factory $authFactory,
    AUser $user,
) {
    $user->fill([
        'password' => HashAlias::make('password'),
    ])->save(); // fill + save

    $session->put('bar', 3);

    dispatch(new AJob());
    AJob::dispatch();
    Queue::push(new AJob());
    QueueAlias::push(new AJob());
    Bus::dispatch(new AJob());
    BusAlias::dispatch(new AJob());

    event(new AEvent());
    AEvent::dispatch();
    Event::dispatch(new AEvent());
    EventAlias::dispatch(new AEvent());

    /** @var  \App\Models\User $authUser */
    $authUser->notify(new ANotification());
    $notifications->send([$authUser], new ANotification());
    Notification::send([$authUser], new ANotification());
    NotificationAlias::send([$authUser], new ANotification());

    return [
        request('foo'),
        request()->input('foo'),
        app('request')->get('foo'),
        $app['request']->input('foo'),
        $injectedRequest->query->get('foo'),
        RequestFacade::query('foo'),
        RequestAlias::input('foo'),
        RequestRealTimeFacade::get('foo'),

        '###################################',

        request()->user(),
        $authUser,
        auth()->user(),
        Auth::user(),
        AuthAlias::user(),
        app('auth')->user(),
        $authFactory->guard('web')->user(),

        '###################################',

        $user,
        request('user'),
        request()->user,
        request()->route('user'),
        request()->route()->parameter('user'),
        $injectedRequest->route()->parameters['user'],
        $injectedRequest->route()->user,
        resolve('request')->route('user'), // resolve() is an alias to app()

        '###################################',

        $session->get('bar'),
        $injectedRequest->session()->get('bar'),
        SessionFacade::get('bar'),
        SessionAlias::get('bar'),
        session('bar'),
        session()->get('bar'),
        app('session')->get('bar'),

        '###################################',

        User::all(),
        User::query()->get(),
        DB::table('users')->get(),
    ];
})->middleware('auth:web');

// could keep on with how to define route groups with prefixes, aliases, ...

Laravel has always been a highly opinionated framework

Agreed.

But its strength is precisely getting out the way of the developer, so they have to worry mostly with their own business logic, and not with implementation details.

It provides sensible defaults, while still allowing a developer to stick with any style they want.

@danabrey
Copy link

Honestly, since Laravel offers the option to return almost anything from a Controller, it'd be better to remove the type-hints altogether from the Controller stubs. There's just no way to cover every single use case and combination. Trying to do so will result in a Cartesian Explosion.

People can still add a return type of their own if they wish, or just ignore it.

This is entirely sensible. You're stubbing out userland code, this isn't internal Laravel code, so adding useless return types that only have any meaning once the developer has changed them is arbitrary.

@devellopah
Copy link

I propose to add property to app.php

'defaultControllerTemplate' => 'blade' // or 'inertia'

If blade option is set then php artisan make:controller MyController should scaffold this template.
If inertia option is set then php artisan make:controller MyController should scaffold this template.

So if you're building project with Inertia, you just change property value to inertia.

I also propose to add flags --blade and --inertia to php artisan make:controller command in order to manually scaffold templates.

php artisan make:controller --blade to scaffold this template
php artisan make:controller --inertia to scaffold this template

@rodrigopedra
Copy link
Contributor

@devellopah

One can already customize the stubs (templates) used by all make: commands, on a per-project basis, by exporting all stubs using this command:

php artisan stub:publish

reference: https://laravel.com/docs/10.x/artisan#stub-customization

@Pluuk
Copy link

Pluuk commented Feb 27, 2023

I feel like the main argument against an interface like Illuminate\Contracts\Support\Responsable is that return values like arrays and strings won't be supported.

What about extending Response with something like fromString() and fromArray() methods. Or maybe even something like fromNativeType(). Then, objects would be able to implement the Responsable interface, and native types should passed to the Response interface with the fromNativeType() function.

@dennisprudlo
Copy link
Contributor

@Pluuk this is already possible with response('whatever') or response([ 1, 2, 3 ]) or Response::make(...) if you would like to use a facade. This however doesn't solve return 'whatever';

Although I am a heavy user of types I think no types by default as it is right now is the best option.

// this is not an issue:
public function method()
{
    return view('foo');
}

// this however is:
public function method(): Responsable
{
    return [ 'bar' ];
}

the second option simply includes more use cases by default. And if anyone want's to lock down the first method to views, that it can be done either in the controller itself or in published stubs.

@sadathimel
Copy link

Noob question

Doesn't this kill the whole purpose of return types?

What's the difference between this and no return types at all

And cant we instead do something like this

Response|View etc

Thank you, you mentioned the obvious. Why hit zend_gc_collector with garbage it cannot even collect? The streets gonna stink like all the previous versions of php

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet