lorisleiva / laravel-actions

⚡️ Laravel components that take care of one specific task
https://laravelactions.com
MIT License
2.52k stars 124 forks source link

How you re-use actions with API and Web #192

Closed sviluppatoreLaRegione closed 1 month ago

sviluppatoreLaRegione commented 2 years ago

Having single asController method, and single routes defined in the Action class, how you are handling API / Web endpoints?

I see there is two method for handleResponse when request is application/json, but sometimes also the Web make a request with application/json header, example request via ajax.

I just start play with the package, and I found not so clear mixin different app like web, api, console, etc...

How you feel with this setup?

Thanks!

leandrodiogenes commented 2 years ago

Maybe you can try to use htmlResponse method. Check this https://deploy-preview-7--laravel-actions.netlify.app/2.x/as-controller.html#htmlresponse https://deploy-preview-7--laravel-actions.netlify.app/2.x/as-controller.html#jsonresponse

sviluppatoreLaRegione commented 2 years ago

Thanks for your reply.

I have already see those methods, but as I said also my web app could request JSON response like with an ajax request.

In API app my JSON response could be different from JSON response for Web app.

Or for example let's say you have to send JSON response to Inertia app and to API app, different JSON response, so you have to do that in jsonResponse method checking the header if there is x-inertia or something like that..

Maybe two new decorator could solve this, like asApi() and asInertia(), and asController remain for asWeb()

santutu commented 2 years ago

GetArticle.php

public function asApi(ActionRequest $req, int $id): JsonResponse {
        $req->validate();
        $article = $this->handle(articleId: $id);
        return response()->json($article);
    }

api.php

Route::get('articles/{id}', [\Modules\Board\Actions\Article\GetArticle::class, 'asApi']);

it works. but idk that need to call refreshAction, refreshRequest in ControllerDecorator.php

sviluppatoreLaRegione commented 2 years ago

I am sure there are several workaround, but I would like to have a native way from this package.

santutu commented 2 years ago

It is fully native friendly. I took a look at codes inside this package . You don't need to call $req->validate().

sviluppatoreLaRegione commented 2 years ago

Fully native would be that when I define a route like below in web.php:

Route::post('articles', PublishANewArticle::class);

Then it run asController

While when I define a route like this in api.php:

Route::post('api/articles', PublishANewArticle::class);

then it run asApi()

Or when I define a route like this in web.php:

Route::post('articles', PublishANewArticle::class);

and the header has X-inertia then it run asInertia() with response for inertia.

Your works fine because you can run as normal object any custom method you define.

jameshulse commented 2 years ago

As far as I can tell from how routing in Laravel works, you are asking too much of the library. The 'web' and 'api' route files are just a convention. You can change what these are called, change their namespacing/grouping etc. It's all configurable. So the library would have no way to tell what the intention of your route was without you specifying.

Maybe you can get the route namespace from the Request and do your own conditional logic to return different responses.

sviluppatoreLaRegione commented 2 years ago

I can handle this for sure, but it could be possible also to do this in the library, why not?

I am not sure what you mean by "route namespace from the request", do you mean the url prefix?

Like

if($request->route()->getPrefix() === 'api') {
   // is api
}

Yes this could works, so it could also be added in the library, where the api route prefix is configurable.

But we have also Request::wantsJson and Request::expectsJson that could be used.

And for intertia we can use also header to detect if is inertia request.

So I don't think to ask to much from the library.

Since now days we have several controller endpoint and not just one, if this library claim to offer single action for everything, why not also for this?

AlexisVS commented 1 year ago

I also use the package in a similar manner. Initially, I utilized the package as a controller to manage the logic implementation of my domain. However, I have now transitioned to using it as a Presenter for the three interfaces: API, WEB, and Command. I've moved my implementation logic inside a Service and others to maintain a cleaner code structure.

When testing with tools like Postman, if the Content-Type of the request is set to plain/html, it renders an Inertia Response but throws an error log. This occurs because 'asController' or 'htmlResponse' expects an Illuminate\Http\Response.

Does anyone have any ideas on how to resolve this issue?

Wulfheart commented 1 month ago

Closing due to inactivity. If you feel your issue is still relevant please open a new one with a link to a repository containing a minimal reproducible example.