In Laravel 11, I’m trying to make a single interface for all of the CRUD resource controllers in my API. Something like this (showing for store()
method only):
<?php
namespace AppInterfaces;
use IlluminateHttpRequest;
use IlluminateHttpJsonResponse;
use IlluminateFoundationHttpFormRequest;
interface ResourceInterface
{
/**
* Store a newly created resource in storage.
*
* @param T $request
* @return JsonResponse
*/
public function store($request): JsonResponse;
And then in the UserController@store
:
<?php
namespace AppHttpControllersApiV1;
use IlluminateHttpRequest;
use IlluminateHttpJsonResponse;
use AppInterfacesResourceInterface;
use AppHttpRequestsStoreUserRequest;
use AppHttpControllersApiApiController;
class UserController extends ApiController implements ResourceInterface
{
public function __construct(private AuthController $authController)
{
}
public function store(StoreUserRequest $request): JsonResponse
{
$user = $this->authController->register($request);
return $this->createdResponse($user, "User {$request->name} registered successfully");
}
As you can see, the UserController@store method uses a custom request class, which will be the case for all of my other resource controller methods. However, I have not been able to make the generic interface work.
I have tried using the FormRequest
class in the controller method, as such:
public function store(FormRequest $request): JsonResponse
{
if (!$request instanceof StoreUserRequest) {
return $this->errorResponse("Invalid request type");
}
$request->validate();
$user = $this->authController->register($request);
return $this->createdResponse($user, "User $request->name registered succesfully");
}
Together with replacing the generic interface with one that uses FromRequest
, since my StoreUserRequest
class extends FormRequest
, but this did not work as the custom validation was not being applied.
And using PHPDoc comments as such:
public function store(FormRequest $request): JsonResponse
{
/** @var StoreUserRequest $request */
$user = $this->authController->register($request);
return $this->createdResponse($user, "User $request->name registered succesfully");
}
But none of these seem to work. What am I dowing wrong?,
2
Answers
Seems like this is not possible or at least evil since it violates contravariance, and the way forward is to rethink the structure around my controller methods and my usage of interfaces.
Let try Laravel’ service container:
https://laravel.com/docs/11.x/container#contextual-binding
Your case:
Add this code in boot function of AppServiceProvider