Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Ortix's avatar

Handling form validation in self consumed API

I'm building a website with a built in API which I'm consuming myself. However, I have come across a problem I can't seem to solve.

I have a Screenshot API which accepts certain post data. When consuming the API myself, I submit a form to a route like so:

    Route::post('episode/screenshot', ['as' => 'screenshot.store', function () {
        HMVC::post('api/screenshot', Input::all());
        return Redirect::back();
    }]);

I have a validator in the store method in the API like so:

    $data = Input::only(['filename', 'url', 'episode_id', 'timecode']);
    try {
        $this->screenshotForm->validate($data);
    } catch (FormValidationException $e) {
        // what do?
    }

The question is: If I consume the API inside my own application using the form I want to return to the form with the validation errors. But when I consume the API RESTfully (e.g. cURL or Postman etc.) I want it to return a json representation of the validation errors.

How do I solve this problem?

My rules:

    protected $rules = [
        'timecode'   => 'required|date_format:H:i:s',
        'filename'   => 'required',
        'episode_id' => 'required|integer',
        'url'        => 'required|url',
    ];
0 likes
12 replies
pmall's avatar

Request class has a wantsJson method that returns true when json is wanted. I think it is the case with cURL or at least you can specify it in the request headers. So if you request wants json you can return json errors, otherwise act as normal.

Ortix's avatar

Is that something I should put in the controller? Because there are several responses in that store method in case something goes wrong.

pmall's avatar

Show your full method.

But yes in the controler you check if the request wantsJson, if true you return a json encoded string of errors.

pmall's avatar

Basically :

$data = Input::only(['filename', 'url', 'episode_id', 'timecode']);
try {
  $this->screenshotForm->validate($data);
} catch (FormValidationException $e) {

  // If json wanted returns json encoded string of errors
  if(Request::wantsJson()) return Response::json($e->getErrors());

  // if not redirect
  return Redirect::back()->withInput()->withErrors($e->getErrors());

}
1 like
Ortix's avatar

The store() method:

public function store()
{
    $data = Input::only(['filename', 'url', 'episode_id', 'timecode']);
    try {
        $this->screenshotForm->validate($data);
    } catch (FormValidationException $e) {
        if (!Request::wantsJson()) {
            return Redirect::back()->withErrors($e->getErrors());
        }
        return $this->invalidForm($e->getErrors());
    }
    $torrent_dir = base_path() . '/tmp/';
    $timecode = $data['timecode'];
    $episode_id = $data['episode_id'];
    try {
        $torrent = $this->getTorrent($torrent_dir, $data);
    } catch (Exception $e) {
        return $this->remoteResourceNotFound($e->getMessage());
    }
    if ($torrent) {
        $force = true; // force this torrent and do not check for better quality
        Queue::push('\Animekyun\Queues\Screenshot', compact('torrent', 'episode_id', 'timecode', 'force'));
        return Response::json([
            'data' => 'Queued ' . $torrent . ' for screenshot. You have to manually navigate back for now'
        ], 200);
    } else {
        return Response::json([
            'error' => 'Something went wrong trying to queue ' . $torrent . ' for screenshot'
        ], 500);
    }
}
pmall's avatar

So what is wrong I don't understand

Ortix's avatar

Sorry for not being clear, my fault.

I guess i'm having a hard time understanding how to handle responses in an API which is also consumed internally. I think wrapping each statement in an if is a bit overkill. But I think your method will do.

pmall's avatar

There is no differences if it is consumed externally or internally or maybe im missing something ?

Ortix's avatar

Well there is not really a difference in consumption except for when it comes down to handling errors and responses. So when I have an API which I use internally and expose to the outside world there are issues with the user experience.

Usually API's return json responses. Which is fine for external use, but when consuming internally json makes it a mess to use.

Perhaps I have to create some sort of response class (or extend the Response class) which handles that :)

A simple example is validation errors. I can't keep wrapping validation exceptions in if statements for json requests and internal requests. Same goes for any other response.

pmall's avatar

Sorry but I dont understand anything. Maybe others could help you.

kodeine's avatar
kodeine
Best Answer
Level 3

Well for me that code is overkill, Have you looked at dingo/api? Consider using that, it has internal requests too. And you can catch exceptions globally using Api::error() function which of course is an api function so your json issues will be solved and you dont need to try catch several times in each method.

Ortix's avatar

Dingo/api is already on the list, but I couldn't get it to work properly. Guess I'll just have to buckle up and take it for another spin. Thanks for the help you guys!

Please or to participate in this conversation.