andyjameswhite's avatar

Developing with Jetstream/Inertia/Vue - Actions or Controllers?

So developing my first App in Jetsream (Inertia/Vue flavour) and looking for opinions... is there any disadvantage to using Actions instead of Controllers?

Jetstream + I/V look great and really impressed with what you get out of the box, pretty powerful stuff, perfect for what I need.

I've done a bit of reading around keeping your Controllers and Models thin using Actions, which really appeals as I always try to keep the Controllers thin but the models take on a bit of a life of their own.

Actions seems like a logical way to organise reusable code and seperate from the Http layer. Jetstream/Fortify use this approach of course within the default install.

So it seems like no major downside, but maybe I'm missing something?

I've not gone too far with this Stack - so I'm a bit in the dark - perhaps the Controllers play nicer with Inertia, or whatever.

Thoughts?

0 likes
4 replies
LaryAI's avatar
Level 58

When developing with Jetstream, Inertia, and Vue, the choice between using Actions or Controllers can depend on your specific needs and preferences. Here's a breakdown of the considerations:

Actions vs. Controllers

  1. Separation of Concerns:

    • Actions: They help in separating business logic from the HTTP layer. This can lead to cleaner and more maintainable code, as each action is responsible for a specific task.
    • Controllers: Traditionally, they handle HTTP requests and responses. However, they can become bloated if they contain too much business logic.
  2. Reusability:

    • Actions: They are highly reusable across different parts of your application. If you have logic that needs to be executed in multiple places, actions can be a great way to encapsulate that logic.
    • Controllers: While you can reuse methods by calling them from different routes, it’s not as clean as using actions.
  3. Testability:

    • Actions: They are easier to test in isolation since they don't depend on the HTTP layer. You can test the business logic without worrying about request/response objects.
    • Controllers: Testing can be more complex as you often need to mock HTTP requests and responses.
  4. Jetstream/Fortify Approach:

    • Jetstream and Fortify use actions extensively, which can serve as a good example of how to structure your application. Following this pattern can make your codebase more consistent with these tools.
  5. Integration with Inertia:

    • Controllers: They work well with Inertia, as Inertia expects controllers to return responses that it can handle (like JSON or Inertia responses).
    • Actions: You can still use actions with Inertia by calling them from within your controllers. This way, you keep the controller thin and delegate the business logic to actions.

Conclusion

There is no major downside to using actions instead of controllers, especially if you prefer a clean separation of concerns and reusable code. However, you might still need controllers to handle the HTTP layer and interact with Inertia. A common pattern is to use controllers to handle requests and responses, and delegate the business logic to actions.

Here's a simple example of how you might structure this:

// Action: CreatePostAction.php
namespace App\Actions;

class CreatePostAction
{
    public function execute(array $data)
    {
        // Business logic for creating a post
        return Post::create($data);
    }
}

// Controller: PostController.php
namespace App\Http\Controllers;

use App\Actions\CreatePostAction;
use Illuminate\Http\Request;

class PostController extends Controller
{
    public function store(Request $request, CreatePostAction $action)
    {
        $post = $action->execute($request->all());

        return redirect()->route('posts.show', $post);
    }
}

In this setup, the PostController handles the HTTP request and response, while the CreatePostAction encapsulates the business logic for creating a post. This keeps your controller thin and your business logic reusable and testable.

martinbean's avatar
Level 80

@andyjameswhite “Actions” don’t replace controllers. Actions are just classes that encapsulate some business logic. You still need a controller to actually invoke the action in response to a HTTP request:

class FooController
{
    public function fooMethod(FooAction $action)
    {
        $action->handle();

        // Return response...
    }
}

An action doesn’t magically know when to invoke itself, and with what parameters.

andyjameswhite's avatar

@martinbean Yeah thanks my questions was poorly phrased I see that reading it back.

I get the controller has to trigger the action, it was just whether the Actions was a good approach.

I've been going with Actions to hold the business logic and it feels much nicer to me to keep the code divided up like that

Also helpful for commands etc, I guess anywhere your reusing the same logic but with a different trigger

martinbean's avatar

@andyjameswhite Yes, that’s the purpose of actions, really: to encapsulate business logic that can then be invoked via various means, i.e. in a controller action, in an Artisan command, in a queued job class, etc.

They’re essentially just self-handling commands without the need of a command bus.

Please or to participate in this conversation.