DEV Community

Mesak
Mesak

Posted on

Laravel Controller use callAction to meke ApiController

In most projects, the controller will be used to return the response to specify JSON to determine the content.

I found that in laravel's routing, ControllerDispatcher uses callback function to call the corresponding Method

Illuminate\Routing\ControllerDispatcher

    public function dispatch(Route $route, $controller, $method)
    {
        $parameters = $this->resolveClassMethodDependencies(
            $route->parametersWithoutNulls(), $controller, $method
        );

        if (method_exists($controller, 'callAction')) {
            return $controller->callAction($method, $parameters);
        }

        return $controller->{$method}(...array_values($parameters));
    }
Enter fullscreen mode Exit fullscreen mode

You can see that the Controller will check whether your Controller has a function called callAtion before executing it. If not, it will return and call the Controller method specified by the route.

This led me to an idea that when Controller implements API or WEB routing, it must return a response to display content

Among them, most people will unify json for API return, but the implementation methods are quite diverse.

I have seen the Response::macro method, or the ApiResponseTrait method, but this method will make me feel difficult to maintain later,

You will see that your Controller will have a lot of judgments to return 200 or 400 or 200 + content of http status code.

API Controller

In my own project, I built an ApiController, let all the content under the API folder in the route inherit ApiController, intercept all results, and convert them into API Response

ApiController

    public function callAction($method, $parameters)
    {
        $result =  $this->{$method}(...array_values($parameters));
        $httpStatus = ($method  === 'store') ? 201 : 200;
        if ($result instanceof ResponseSchema) {
            $response = &$result;
        } else {
            $response = new ResponseSchema($result);
        }
        $response->setStatus($httpStatus);
        return response()->json($response, $httpStatus);
    }
Enter fullscreen mode Exit fullscreen mode

I created a ResponseSchema Class, specifically defined the JSON Schema format, and then returned it uniformly. The content returned by the Controller will be the result of successful execution. The only small difference is that the newly added method is unified and I call it store, which will put http status code returns 201.

Since only successful information is returned here, the Controller does not need to write a bunch of try catches, and can focus on returning the necessary information.

Error Handler

How to handle error handling? According to the-exception-handler mentioned on the official website, there is a special error handling Handler for errors, so only App\Exceptions\Handler , This program focuses on handling errors. Loading ResponseSchema in the render function and spit out the corresponding method can unify the JSON Response Schema.

    public function render($request, Throwable $exception)
    {
        $responseSchema = new ResponseSchema();
        $statusCode = 500;
        $responseSchema->setException($exception);
        $responseSchema->setMessage('Server Error');
        $responseSchema->setStatus($statusCode);
        if ($request->is(['api/*', 'oauth/*'])) {
            $request->headers->set('Accept', 'application/json');
            return response($responseSchema->toArray(), $statusCode);
        }
        return parent::render($request, $exception);
    }

Enter fullscreen mode Exit fullscreen mode

At present, this method is my current method of implementing API Response, so that I can focus on Controller writing and achieve the purpose of hierarchical division of labor

Top comments (0)