laravel-actions icon indicating copy to clipboard operation
laravel-actions copied to clipboard

How you re-use actions with API and Web

Open sviluppatoreLaRegione opened this issue 2 years ago • 9 comments

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!

sviluppatoreLaRegione avatar Aug 22 '22 18:08 sviluppatoreLaRegione

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()

sviluppatoreLaRegione avatar Aug 22 '22 20:08 sviluppatoreLaRegione

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

santutu avatar Sep 03 '22 02:09 santutu

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

sviluppatoreLaRegione avatar Sep 05 '22 17:09 sviluppatoreLaRegione

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

santutu avatar Sep 23 '22 07:09 santutu

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.

sviluppatoreLaRegione avatar Sep 23 '22 17:09 sviluppatoreLaRegione

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.

jameshulse avatar Oct 18 '22 21:10 jameshulse

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?

sviluppatoreLaRegione avatar Oct 30 '22 16:10 sviluppatoreLaRegione

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?

AlexisVS avatar Oct 27 '23 10:10 AlexisVS