skip to Main Content

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


  1. Chosen as BEST ANSWER

    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.


  2. Let try Laravel’ service container:
    https://laravel.com/docs/11.x/container#contextual-binding

    Your case:

    $this->app->when(UserController::class)
              ->needs(FormRequest::class)
              ->give(YourExtendClassOfFormRequest);
    

    Add this code in boot function of AppServiceProvider

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search