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

clodoaldobragato's avatar

API Route, Middleware and FormRequest

Dear friends,

I have the following need:

  1. Create an API to add some data to the database
  2. Create a FormRequest to validate this data
  3. Create a Middleware that modifies some of these data before persiting them.

Well, I followed these steps, but my middleware does not fire when I call the API.

I registered it in App \ Http \ Kernel.php, and added it to the route in the API route file.

Can someone help me?

To complement this information the Laravel Version is 5.8.10

Controller:

use App\Http\Requests\Customer\CustomerRequest;
class CustomerController extends Controller
{

  public function add(CustomerRequest $request){

    $fullname = $request->input('firstname').' '.$request->input('lastname');
    $customer = Customer::firstOrCreate(["name"=>$fullname,]);
    $customer->user()->firstOrCreate($request->all());

    return response()->json($customer->with(["user"]),200);

  }
}

api.php

Route::prefix('customer')->group(function(){
    Route::post('/','Api\Customer\CustomerController@add')->middleware('customer');
});

CustomerRequest.php

namespace App\Http\Requests\Customer;

use Illuminate\Foundation\Http\FormRequest;

class CustomerRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
          'email'=>'required|email|unique:users,email',
          'firstname'=>'required|string|min:5|max:20',
          'lastname'=>'required|string|min:1|max:100',
          'hash'=>'required|string|min:6|max:255',
        ];
    }

    public function messages(){
      return [
        'email.required'=>__('e-Mail is required'),
        'email.email'=>__('e-Mail must be a valid address'),
        'email.unique'=>__('This e-Mail is already registered'),
        'firstname.required'=>__('Firstname is required'),
        'firstname.string'=>__('Firstname must be a string'),
        'firstname.min'=>__('Fisrtname must have a minimal of 5 characters'),
        'firstname.max'=>__('Fisrtname must have a maximal of 20 characters'),
        'lastname.required'=>__('Lastname is required'),
        'lastname.string'=>__('Lastname must be a string'),
        'lastname.min'=>__('Lastname must have a minimal of 1 characters'),
        'lastname.max'=>__('Lastname must have a maximal of 100 characters'),
        'hash.required'=>__('Password is required'),
        'hash.string'=>__('Password must be a string'),
        'hash.min'=>__('Password must have a minimal of 6 characters'),
        'hash.max'=>__('Password must have a maximal of 255 characters'),
      ];
    }
}

CustomerMiddleware.php

namespace App\Http\Middleware\Customer;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Symfony\Component\HttpFoundation\ParameterBag;
use App\Http\Requests\Customer\CustomerRequest;

class CustomerMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle(CustomerRequest $request, Closure $next)
    {

      if($request->isJson()){
        $this->modify($request->json());
      }else{
        $this->modify($request->request);
      }

      return $next($request);
    }

    private function modify(ParameterBag $bag){
      $bag->replace($this->modifyData($bag->all()));
    }

    private function modifyData(array $data){
      return collect($data)->map(function($value,$key){
        switch ($key) {
          case 'firstname':
            return ucwords(strtolower($value));
            break;
          case 'lastname':
            return ucwords(strtolower($value));
            break;
          case 'hash':
            return Hash::make($value);
            break;
        }
      })->all();
    }
}

Kernel.php

    /**
     * The application's route middleware.
     *
     * These middleware may be assigned to groups or used individually.
     *
     * @var array
     */
    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
        'user' => \App\Http\Middleware\Authentication\UserMiddleware::class,
        'customer' => \App\Http\Middleware\Customer\CustomerMiddleware::class,
    ];
0 likes
13 replies
steve_laracasts's avatar

Is your prefix correct, seems a bit odd to me now I notice it, it works like this:

Route Prefixes
The prefix method may be used to prefix each route in the group with a given URI. For example, you may want to prefix all route URIs within the group with admin:

Route::prefix('admin')->group(function () {
    Route::get('users', function () {
        // Matches The "/admin/users" URL
    });
});
clodoaldobragato's avatar

Yes, the prefix works fine! The controller is called and the operation is complete, but the transformation made by middleware does not occurs. In some times i tried to user Dump and Die function on handler of middlewere, but does not run. I think the middleware does not fire on call the API!

munazzil's avatar

Your using firstOrCreate it throws error because it gives only first result use createorupdate.

     $customer = Customer::createOrUpdate(["name"=>$fullname,]);
     $customer->user()->createOrUpdate($request->all());
clodoaldobragato's avatar

@MUNAZZIL - Sorry @munazzil, the controller works fine, the data persintence works fine. The middleware dont fire before controller method call. This is the real problem.

rodriguesbruno's avatar

Have you tried using a plain Illuminate\Http\Request instead of your custom Request as parameter for the handle method in the middleware class?

I am not sure if you should be using custom requests there...

Edit: adding code sample

public function handle(Request $request, Closure $next)
{
  ... 
}  

clodoaldobragato's avatar
Level 1

@RODRIGUESBRUNO - Hi @rodriguesbruno, thank you for response, but i discovery the problem. The real problem is on the Route:

My original route is :

Route::prefix('customer')->group(function(){
    Route::post('/','Api\Customer\CustomerController@add')->middleware('customer');
});

But the route should be:

Route::prefix('customer')->group(function(){
    Route::middleware('customer')->post('/','Api\Customer\CustomerController@add');
});

The middleware call must be made before the controller call

Now this works fine.

1 like
foudadev's avatar

@clodoaldobragato I have a problem with the request validation class if there is an error with the validation it doesn't display any error message how i can handle them in the request class

Sinnbeck's avatar

@foudadev If the answer isnt already in the thread, I suggest you create a new one describing your exact problem

rodriguesbruno's avatar

We'll this is pretty weird since I have used your code on my local environment and having the ->middleware worked fine. Anyway, I'm happy that you solved it!

steve_laracasts's avatar

Cool, glad you sorted this!!

I knew that route didn't look right, sorry I didn't spot what it was that was bugging me about it, will definitely make a mental note about this because it's something I will probably do at some point. Thank you for sharing your answer.

Please or to participate in this conversation.