For me, the root cause of all problems here is the fact that you’re establishing communication…
Marco Aurélio Deleu

Yes, there is a communication between controllers, but it’s basically simulating an HTTP request.

There are some big cons to this approach:

  1. Middlewares on API endpoint won’t be executed (for example rate-limiting)
  2. You may have some caching in front of your API (varnish/Nginx). This will overpass it.
  3. But the biggest problem is, as you said … Form Request validation

There are some options to make it work:

Make same request object, initialize values, call validate and then pass it to the controller:

$req = app(PostsRequest::class);
$req->initialize(['per_page' => 5, 'category' => 32]);

$posts = app(PostsController::class)->index($req);

Validate inside the controller (this will be more common in Laravel 5.5 with new $request->validate):

$this->validate($request, [
'category' => 'integer'

I don’t like any of them. But to be honest I mostly use this approach (direct action call) only for simulating GET request with known parameters (no user input). If there is user data, more advanced validation … I still prefer making an API call.