Laravel Validation Request & API route POST parameter









up vote
0
down vote

favorite












I'm facing a little issue with Form Request Validation and how to handle it with one API route.



The resource that I need to create depends on an other resource.



(Here an EmailSettings belongs to a Tenant)



So the look of my route should be something like : /api/tenants/id/email_settings



And my request validation expects several fields including the tenantId :



public function rules() required


And I send the request like this :



try 
const response = await this.tenantForm.post('/api/tenants')
let newTenant = helpers.getNewResourceFromResponseHeaderLocation(response)
let tenantId = parseInt(newTenant.id);
try
await this.emailSettingsForm.post('/api/tenants/' + tenantId + '/email_settings')
this.requestAllTenants()
catch (response)
$('.second.modal').modal(blurring: true, closable: false).modal('show');

catch (response)
$('.first.modal').modal(blurring: true).modal('show');



So the tenantId is passed as a parameter and not in the request body to respect the REST convention.
But the problem is in my Controller, when I merge the data to create the resource, the validation has already took place only on body data before the merge.



public function store(EmailSettingValidation $request, $tenant_id) 
$emailSetting = $this->emailSettingService->create(
array_merge($request->all(), compact($tenant_id))
);
return $this->response->created($emailSetting);



So what is the best way to handle it properly ?



  • Pass the id in the body ? Seems messy

  • Use Validator to validate manually ? I would prefer to keep Form Validation

  • Remove the tenantId rule and check it manually ?

Any suggestions ?
Thank you










share|improve this question























  • Do you have a model for your tenant table?
    – Travis Britz
    Nov 9 at 13:57










  • @TravisBritz Yes, but why is it important?
    – guillaumehanotel
    Nov 9 at 14:01














up vote
0
down vote

favorite












I'm facing a little issue with Form Request Validation and how to handle it with one API route.



The resource that I need to create depends on an other resource.



(Here an EmailSettings belongs to a Tenant)



So the look of my route should be something like : /api/tenants/id/email_settings



And my request validation expects several fields including the tenantId :



public function rules() required


And I send the request like this :



try 
const response = await this.tenantForm.post('/api/tenants')
let newTenant = helpers.getNewResourceFromResponseHeaderLocation(response)
let tenantId = parseInt(newTenant.id);
try
await this.emailSettingsForm.post('/api/tenants/' + tenantId + '/email_settings')
this.requestAllTenants()
catch (response)
$('.second.modal').modal(blurring: true, closable: false).modal('show');

catch (response)
$('.first.modal').modal(blurring: true).modal('show');



So the tenantId is passed as a parameter and not in the request body to respect the REST convention.
But the problem is in my Controller, when I merge the data to create the resource, the validation has already took place only on body data before the merge.



public function store(EmailSettingValidation $request, $tenant_id) 
$emailSetting = $this->emailSettingService->create(
array_merge($request->all(), compact($tenant_id))
);
return $this->response->created($emailSetting);



So what is the best way to handle it properly ?



  • Pass the id in the body ? Seems messy

  • Use Validator to validate manually ? I would prefer to keep Form Validation

  • Remove the tenantId rule and check it manually ?

Any suggestions ?
Thank you










share|improve this question























  • Do you have a model for your tenant table?
    – Travis Britz
    Nov 9 at 13:57










  • @TravisBritz Yes, but why is it important?
    – guillaumehanotel
    Nov 9 at 14:01












up vote
0
down vote

favorite









up vote
0
down vote

favorite











I'm facing a little issue with Form Request Validation and how to handle it with one API route.



The resource that I need to create depends on an other resource.



(Here an EmailSettings belongs to a Tenant)



So the look of my route should be something like : /api/tenants/id/email_settings



And my request validation expects several fields including the tenantId :



public function rules() required


And I send the request like this :



try 
const response = await this.tenantForm.post('/api/tenants')
let newTenant = helpers.getNewResourceFromResponseHeaderLocation(response)
let tenantId = parseInt(newTenant.id);
try
await this.emailSettingsForm.post('/api/tenants/' + tenantId + '/email_settings')
this.requestAllTenants()
catch (response)
$('.second.modal').modal(blurring: true, closable: false).modal('show');

catch (response)
$('.first.modal').modal(blurring: true).modal('show');



So the tenantId is passed as a parameter and not in the request body to respect the REST convention.
But the problem is in my Controller, when I merge the data to create the resource, the validation has already took place only on body data before the merge.



public function store(EmailSettingValidation $request, $tenant_id) 
$emailSetting = $this->emailSettingService->create(
array_merge($request->all(), compact($tenant_id))
);
return $this->response->created($emailSetting);



So what is the best way to handle it properly ?



  • Pass the id in the body ? Seems messy

  • Use Validator to validate manually ? I would prefer to keep Form Validation

  • Remove the tenantId rule and check it manually ?

Any suggestions ?
Thank you










share|improve this question















I'm facing a little issue with Form Request Validation and how to handle it with one API route.



The resource that I need to create depends on an other resource.



(Here an EmailSettings belongs to a Tenant)



So the look of my route should be something like : /api/tenants/id/email_settings



And my request validation expects several fields including the tenantId :



public function rules() required


And I send the request like this :



try 
const response = await this.tenantForm.post('/api/tenants')
let newTenant = helpers.getNewResourceFromResponseHeaderLocation(response)
let tenantId = parseInt(newTenant.id);
try
await this.emailSettingsForm.post('/api/tenants/' + tenantId + '/email_settings')
this.requestAllTenants()
catch (response)
$('.second.modal').modal(blurring: true, closable: false).modal('show');

catch (response)
$('.first.modal').modal(blurring: true).modal('show');



So the tenantId is passed as a parameter and not in the request body to respect the REST convention.
But the problem is in my Controller, when I merge the data to create the resource, the validation has already took place only on body data before the merge.



public function store(EmailSettingValidation $request, $tenant_id) 
$emailSetting = $this->emailSettingService->create(
array_merge($request->all(), compact($tenant_id))
);
return $this->response->created($emailSetting);



So what is the best way to handle it properly ?



  • Pass the id in the body ? Seems messy

  • Use Validator to validate manually ? I would prefer to keep Form Validation

  • Remove the tenantId rule and check it manually ?

Any suggestions ?
Thank you







laravel rest api validation






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 9 at 14:05

























asked Nov 9 at 13:48









guillaumehanotel

14




14











  • Do you have a model for your tenant table?
    – Travis Britz
    Nov 9 at 13:57










  • @TravisBritz Yes, but why is it important?
    – guillaumehanotel
    Nov 9 at 14:01
















  • Do you have a model for your tenant table?
    – Travis Britz
    Nov 9 at 13:57










  • @TravisBritz Yes, but why is it important?
    – guillaumehanotel
    Nov 9 at 14:01















Do you have a model for your tenant table?
– Travis Britz
Nov 9 at 13:57




Do you have a model for your tenant table?
– Travis Britz
Nov 9 at 13:57












@TravisBritz Yes, but why is it important?
– guillaumehanotel
Nov 9 at 14:01




@TravisBritz Yes, but why is it important?
– guillaumehanotel
Nov 9 at 14:01












3 Answers
3






active

oldest

votes

















up vote
0
down vote













If you define your api route like this:





Roue::post('tenants/tenant/emails_settings', 'Controller@store');


and modify your controller method to type-hint the model with a matching variable name:



public function store(EmailSettingValidation $request, Tenant $tenant) 


Laravel will automatically find the Tenant by ID and inject it into the controller, throwing a ModelNotFoundException (404) if it doesn't exist. That should take care of validating the id.



Authorization is another matter.






share|improve this answer




















  • Your solution works well (if we add the middleware 'bindings' to the route) but when the Tenant doesn't exist, it returns "500 : No query results for model [AppTenant]" and not 404 and I don't know why :/
    – guillaumehanotel
    Nov 9 at 14:44










  • @guillaumehanotel what version of Laravel is this?
    – Travis Britz
    Nov 9 at 14:47










  • This is version 5.5
    – guillaumehanotel
    Nov 9 at 14:48










  • @guillaumehanotel does your web middleware group include the IlluminateRoutingMiddlewareSubstituteBindings::class,?
    – Travis Britz
    Nov 9 at 14:50











  • Yes but I defined my routes in the api.php so the web group doesn't apply
    – guillaumehanotel
    Nov 9 at 14:53

















up vote
0
down vote



accepted










So the solution I found to trigger 404 is the following :



  • Remove the tenantId from EmailSettings Validation

  • Add a provider to add a custom error when the exception 'ModelNotFoundException' occurs like here
    No query results for model in Laravel with Dingo - how to make a RESTful response on failure?


  • Try to throw this Exception with the findOrFail method if invalid ID :



    public function store(EmailSettingValidation $request, $tenant_id) 
    Tenant::findOrFail($tenant_id);
    $emailSetting = $this->emailSettingService->create(
    array_merge($request->all(), ['tenantId' => $tenant_id])
    );
    return $this->response->created($emailSetting);







share|improve this answer



























    up vote
    0
    down vote













    Travis Britz and Guillaumehanotel each have half of your answer, but you're still missing a detail.



    From Travis Britz- Yes, include the tenant_id on the URI so it gets injected into the controller.
    From Guillaumehanotel- Also used the Eloquent findOrFail in that Id in your Controller (or whatever class the Controller is leveraging to do this, like a Repository or Service class).



    The last piece you're missing though is handling the error. You can do this in the Controller if you like, but I generally like making it a rule for my entire system that the IlluminateDatabaseEloquentModelNotFoundException Exceptions that come out of findOrFail() should always result in a 404.



    Go to app/Exceptions/Handler.php. I'm pretty sure Laravel auto-generates a meat and potatoes version of this file for you, but if you don't already have one, it should look something like this:



    <?php

    namespace AppExceptions;

    use IlluminateFoundationExceptionsHandler as ExceptionHandler;

    /**
    * Class Handler
    * @package AppExceptions
    */
    class Handler extends ExceptionHandler

    /**
    * Render an exception into an HTTP response.
    *
    * For our API, we need to override the call
    * to the parent.
    *
    * @param IlluminateHttpRequest $request
    * @param Exception $e
    * @return IlluminateHttpResponse
    */
    public function render($request, Exception $error)

    $exception = [
    'title' => 'Internal Error',
    'message' => $error->getMessage();
    ];
    $statusCode = 500;
    $headers = [
    'Content-Type', 'application/json'
    ];

    return response()->json($exception, $statusCode, $headers, JSON_PRETTY_PRINT);




    Laravel basically has a system-wide try/catch that sends all errors through here first. That's how errors get rendered into something the browser can actually interpret when you're in debug-mode, rather than just kill the process outright. This also gives you the opportunity to apply a few special rules.



    So all you need to do is tell Handler::render() to change the default error code that occurs when it sees the type of error that can only come from findOrFail(). (This kind of thing is why it's always good to make your own 'named exceptions', even if they do absolutely nothing except inherit the base Exception class.)



    Just add this just before render() returns anything:



    if ($error instanceof IlluminateDatabaseEloquentModelNotFoundException) 
    $statusCode = 404;






    share|improve this answer




















    • This is already the default behavior of Laravel. The reason for the 500 status code is an external library they're using (dingo/api) that has its own exception handling.
      – Travis Britz
      Nov 10 at 4:45











    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53226948%2flaravel-validation-request-api-route-post-parameter%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    0
    down vote













    If you define your api route like this:





    Roue::post('tenants/tenant/emails_settings', 'Controller@store');


    and modify your controller method to type-hint the model with a matching variable name:



    public function store(EmailSettingValidation $request, Tenant $tenant) 


    Laravel will automatically find the Tenant by ID and inject it into the controller, throwing a ModelNotFoundException (404) if it doesn't exist. That should take care of validating the id.



    Authorization is another matter.






    share|improve this answer




















    • Your solution works well (if we add the middleware 'bindings' to the route) but when the Tenant doesn't exist, it returns "500 : No query results for model [AppTenant]" and not 404 and I don't know why :/
      – guillaumehanotel
      Nov 9 at 14:44










    • @guillaumehanotel what version of Laravel is this?
      – Travis Britz
      Nov 9 at 14:47










    • This is version 5.5
      – guillaumehanotel
      Nov 9 at 14:48










    • @guillaumehanotel does your web middleware group include the IlluminateRoutingMiddlewareSubstituteBindings::class,?
      – Travis Britz
      Nov 9 at 14:50











    • Yes but I defined my routes in the api.php so the web group doesn't apply
      – guillaumehanotel
      Nov 9 at 14:53














    up vote
    0
    down vote













    If you define your api route like this:





    Roue::post('tenants/tenant/emails_settings', 'Controller@store');


    and modify your controller method to type-hint the model with a matching variable name:



    public function store(EmailSettingValidation $request, Tenant $tenant) 


    Laravel will automatically find the Tenant by ID and inject it into the controller, throwing a ModelNotFoundException (404) if it doesn't exist. That should take care of validating the id.



    Authorization is another matter.






    share|improve this answer




















    • Your solution works well (if we add the middleware 'bindings' to the route) but when the Tenant doesn't exist, it returns "500 : No query results for model [AppTenant]" and not 404 and I don't know why :/
      – guillaumehanotel
      Nov 9 at 14:44










    • @guillaumehanotel what version of Laravel is this?
      – Travis Britz
      Nov 9 at 14:47










    • This is version 5.5
      – guillaumehanotel
      Nov 9 at 14:48










    • @guillaumehanotel does your web middleware group include the IlluminateRoutingMiddlewareSubstituteBindings::class,?
      – Travis Britz
      Nov 9 at 14:50











    • Yes but I defined my routes in the api.php so the web group doesn't apply
      – guillaumehanotel
      Nov 9 at 14:53












    up vote
    0
    down vote










    up vote
    0
    down vote









    If you define your api route like this:





    Roue::post('tenants/tenant/emails_settings', 'Controller@store');


    and modify your controller method to type-hint the model with a matching variable name:



    public function store(EmailSettingValidation $request, Tenant $tenant) 


    Laravel will automatically find the Tenant by ID and inject it into the controller, throwing a ModelNotFoundException (404) if it doesn't exist. That should take care of validating the id.



    Authorization is another matter.






    share|improve this answer












    If you define your api route like this:





    Roue::post('tenants/tenant/emails_settings', 'Controller@store');


    and modify your controller method to type-hint the model with a matching variable name:



    public function store(EmailSettingValidation $request, Tenant $tenant) 


    Laravel will automatically find the Tenant by ID and inject it into the controller, throwing a ModelNotFoundException (404) if it doesn't exist. That should take care of validating the id.



    Authorization is another matter.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 9 at 14:11









    Travis Britz

    1,01946




    1,01946











    • Your solution works well (if we add the middleware 'bindings' to the route) but when the Tenant doesn't exist, it returns "500 : No query results for model [AppTenant]" and not 404 and I don't know why :/
      – guillaumehanotel
      Nov 9 at 14:44










    • @guillaumehanotel what version of Laravel is this?
      – Travis Britz
      Nov 9 at 14:47










    • This is version 5.5
      – guillaumehanotel
      Nov 9 at 14:48










    • @guillaumehanotel does your web middleware group include the IlluminateRoutingMiddlewareSubstituteBindings::class,?
      – Travis Britz
      Nov 9 at 14:50











    • Yes but I defined my routes in the api.php so the web group doesn't apply
      – guillaumehanotel
      Nov 9 at 14:53
















    • Your solution works well (if we add the middleware 'bindings' to the route) but when the Tenant doesn't exist, it returns "500 : No query results for model [AppTenant]" and not 404 and I don't know why :/
      – guillaumehanotel
      Nov 9 at 14:44










    • @guillaumehanotel what version of Laravel is this?
      – Travis Britz
      Nov 9 at 14:47










    • This is version 5.5
      – guillaumehanotel
      Nov 9 at 14:48










    • @guillaumehanotel does your web middleware group include the IlluminateRoutingMiddlewareSubstituteBindings::class,?
      – Travis Britz
      Nov 9 at 14:50











    • Yes but I defined my routes in the api.php so the web group doesn't apply
      – guillaumehanotel
      Nov 9 at 14:53















    Your solution works well (if we add the middleware 'bindings' to the route) but when the Tenant doesn't exist, it returns "500 : No query results for model [AppTenant]" and not 404 and I don't know why :/
    – guillaumehanotel
    Nov 9 at 14:44




    Your solution works well (if we add the middleware 'bindings' to the route) but when the Tenant doesn't exist, it returns "500 : No query results for model [AppTenant]" and not 404 and I don't know why :/
    – guillaumehanotel
    Nov 9 at 14:44












    @guillaumehanotel what version of Laravel is this?
    – Travis Britz
    Nov 9 at 14:47




    @guillaumehanotel what version of Laravel is this?
    – Travis Britz
    Nov 9 at 14:47












    This is version 5.5
    – guillaumehanotel
    Nov 9 at 14:48




    This is version 5.5
    – guillaumehanotel
    Nov 9 at 14:48












    @guillaumehanotel does your web middleware group include the IlluminateRoutingMiddlewareSubstituteBindings::class,?
    – Travis Britz
    Nov 9 at 14:50





    @guillaumehanotel does your web middleware group include the IlluminateRoutingMiddlewareSubstituteBindings::class,?
    – Travis Britz
    Nov 9 at 14:50













    Yes but I defined my routes in the api.php so the web group doesn't apply
    – guillaumehanotel
    Nov 9 at 14:53




    Yes but I defined my routes in the api.php so the web group doesn't apply
    – guillaumehanotel
    Nov 9 at 14:53












    up vote
    0
    down vote



    accepted










    So the solution I found to trigger 404 is the following :



    • Remove the tenantId from EmailSettings Validation

    • Add a provider to add a custom error when the exception 'ModelNotFoundException' occurs like here
      No query results for model in Laravel with Dingo - how to make a RESTful response on failure?


    • Try to throw this Exception with the findOrFail method if invalid ID :



      public function store(EmailSettingValidation $request, $tenant_id) 
      Tenant::findOrFail($tenant_id);
      $emailSetting = $this->emailSettingService->create(
      array_merge($request->all(), ['tenantId' => $tenant_id])
      );
      return $this->response->created($emailSetting);







    share|improve this answer
























      up vote
      0
      down vote



      accepted










      So the solution I found to trigger 404 is the following :



      • Remove the tenantId from EmailSettings Validation

      • Add a provider to add a custom error when the exception 'ModelNotFoundException' occurs like here
        No query results for model in Laravel with Dingo - how to make a RESTful response on failure?


      • Try to throw this Exception with the findOrFail method if invalid ID :



        public function store(EmailSettingValidation $request, $tenant_id) 
        Tenant::findOrFail($tenant_id);
        $emailSetting = $this->emailSettingService->create(
        array_merge($request->all(), ['tenantId' => $tenant_id])
        );
        return $this->response->created($emailSetting);







      share|improve this answer






















        up vote
        0
        down vote



        accepted







        up vote
        0
        down vote



        accepted






        So the solution I found to trigger 404 is the following :



        • Remove the tenantId from EmailSettings Validation

        • Add a provider to add a custom error when the exception 'ModelNotFoundException' occurs like here
          No query results for model in Laravel with Dingo - how to make a RESTful response on failure?


        • Try to throw this Exception with the findOrFail method if invalid ID :



          public function store(EmailSettingValidation $request, $tenant_id) 
          Tenant::findOrFail($tenant_id);
          $emailSetting = $this->emailSettingService->create(
          array_merge($request->all(), ['tenantId' => $tenant_id])
          );
          return $this->response->created($emailSetting);







        share|improve this answer












        So the solution I found to trigger 404 is the following :



        • Remove the tenantId from EmailSettings Validation

        • Add a provider to add a custom error when the exception 'ModelNotFoundException' occurs like here
          No query results for model in Laravel with Dingo - how to make a RESTful response on failure?


        • Try to throw this Exception with the findOrFail method if invalid ID :



          public function store(EmailSettingValidation $request, $tenant_id) 
          Tenant::findOrFail($tenant_id);
          $emailSetting = $this->emailSettingService->create(
          array_merge($request->all(), ['tenantId' => $tenant_id])
          );
          return $this->response->created($emailSetting);








        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 9 at 16:51









        guillaumehanotel

        14




        14




















            up vote
            0
            down vote













            Travis Britz and Guillaumehanotel each have half of your answer, but you're still missing a detail.



            From Travis Britz- Yes, include the tenant_id on the URI so it gets injected into the controller.
            From Guillaumehanotel- Also used the Eloquent findOrFail in that Id in your Controller (or whatever class the Controller is leveraging to do this, like a Repository or Service class).



            The last piece you're missing though is handling the error. You can do this in the Controller if you like, but I generally like making it a rule for my entire system that the IlluminateDatabaseEloquentModelNotFoundException Exceptions that come out of findOrFail() should always result in a 404.



            Go to app/Exceptions/Handler.php. I'm pretty sure Laravel auto-generates a meat and potatoes version of this file for you, but if you don't already have one, it should look something like this:



            <?php

            namespace AppExceptions;

            use IlluminateFoundationExceptionsHandler as ExceptionHandler;

            /**
            * Class Handler
            * @package AppExceptions
            */
            class Handler extends ExceptionHandler

            /**
            * Render an exception into an HTTP response.
            *
            * For our API, we need to override the call
            * to the parent.
            *
            * @param IlluminateHttpRequest $request
            * @param Exception $e
            * @return IlluminateHttpResponse
            */
            public function render($request, Exception $error)

            $exception = [
            'title' => 'Internal Error',
            'message' => $error->getMessage();
            ];
            $statusCode = 500;
            $headers = [
            'Content-Type', 'application/json'
            ];

            return response()->json($exception, $statusCode, $headers, JSON_PRETTY_PRINT);




            Laravel basically has a system-wide try/catch that sends all errors through here first. That's how errors get rendered into something the browser can actually interpret when you're in debug-mode, rather than just kill the process outright. This also gives you the opportunity to apply a few special rules.



            So all you need to do is tell Handler::render() to change the default error code that occurs when it sees the type of error that can only come from findOrFail(). (This kind of thing is why it's always good to make your own 'named exceptions', even if they do absolutely nothing except inherit the base Exception class.)



            Just add this just before render() returns anything:



            if ($error instanceof IlluminateDatabaseEloquentModelNotFoundException) 
            $statusCode = 404;






            share|improve this answer




















            • This is already the default behavior of Laravel. The reason for the 500 status code is an external library they're using (dingo/api) that has its own exception handling.
              – Travis Britz
              Nov 10 at 4:45















            up vote
            0
            down vote













            Travis Britz and Guillaumehanotel each have half of your answer, but you're still missing a detail.



            From Travis Britz- Yes, include the tenant_id on the URI so it gets injected into the controller.
            From Guillaumehanotel- Also used the Eloquent findOrFail in that Id in your Controller (or whatever class the Controller is leveraging to do this, like a Repository or Service class).



            The last piece you're missing though is handling the error. You can do this in the Controller if you like, but I generally like making it a rule for my entire system that the IlluminateDatabaseEloquentModelNotFoundException Exceptions that come out of findOrFail() should always result in a 404.



            Go to app/Exceptions/Handler.php. I'm pretty sure Laravel auto-generates a meat and potatoes version of this file for you, but if you don't already have one, it should look something like this:



            <?php

            namespace AppExceptions;

            use IlluminateFoundationExceptionsHandler as ExceptionHandler;

            /**
            * Class Handler
            * @package AppExceptions
            */
            class Handler extends ExceptionHandler

            /**
            * Render an exception into an HTTP response.
            *
            * For our API, we need to override the call
            * to the parent.
            *
            * @param IlluminateHttpRequest $request
            * @param Exception $e
            * @return IlluminateHttpResponse
            */
            public function render($request, Exception $error)

            $exception = [
            'title' => 'Internal Error',
            'message' => $error->getMessage();
            ];
            $statusCode = 500;
            $headers = [
            'Content-Type', 'application/json'
            ];

            return response()->json($exception, $statusCode, $headers, JSON_PRETTY_PRINT);




            Laravel basically has a system-wide try/catch that sends all errors through here first. That's how errors get rendered into something the browser can actually interpret when you're in debug-mode, rather than just kill the process outright. This also gives you the opportunity to apply a few special rules.



            So all you need to do is tell Handler::render() to change the default error code that occurs when it sees the type of error that can only come from findOrFail(). (This kind of thing is why it's always good to make your own 'named exceptions', even if they do absolutely nothing except inherit the base Exception class.)



            Just add this just before render() returns anything:



            if ($error instanceof IlluminateDatabaseEloquentModelNotFoundException) 
            $statusCode = 404;






            share|improve this answer




















            • This is already the default behavior of Laravel. The reason for the 500 status code is an external library they're using (dingo/api) that has its own exception handling.
              – Travis Britz
              Nov 10 at 4:45













            up vote
            0
            down vote










            up vote
            0
            down vote









            Travis Britz and Guillaumehanotel each have half of your answer, but you're still missing a detail.



            From Travis Britz- Yes, include the tenant_id on the URI so it gets injected into the controller.
            From Guillaumehanotel- Also used the Eloquent findOrFail in that Id in your Controller (or whatever class the Controller is leveraging to do this, like a Repository or Service class).



            The last piece you're missing though is handling the error. You can do this in the Controller if you like, but I generally like making it a rule for my entire system that the IlluminateDatabaseEloquentModelNotFoundException Exceptions that come out of findOrFail() should always result in a 404.



            Go to app/Exceptions/Handler.php. I'm pretty sure Laravel auto-generates a meat and potatoes version of this file for you, but if you don't already have one, it should look something like this:



            <?php

            namespace AppExceptions;

            use IlluminateFoundationExceptionsHandler as ExceptionHandler;

            /**
            * Class Handler
            * @package AppExceptions
            */
            class Handler extends ExceptionHandler

            /**
            * Render an exception into an HTTP response.
            *
            * For our API, we need to override the call
            * to the parent.
            *
            * @param IlluminateHttpRequest $request
            * @param Exception $e
            * @return IlluminateHttpResponse
            */
            public function render($request, Exception $error)

            $exception = [
            'title' => 'Internal Error',
            'message' => $error->getMessage();
            ];
            $statusCode = 500;
            $headers = [
            'Content-Type', 'application/json'
            ];

            return response()->json($exception, $statusCode, $headers, JSON_PRETTY_PRINT);




            Laravel basically has a system-wide try/catch that sends all errors through here first. That's how errors get rendered into something the browser can actually interpret when you're in debug-mode, rather than just kill the process outright. This also gives you the opportunity to apply a few special rules.



            So all you need to do is tell Handler::render() to change the default error code that occurs when it sees the type of error that can only come from findOrFail(). (This kind of thing is why it's always good to make your own 'named exceptions', even if they do absolutely nothing except inherit the base Exception class.)



            Just add this just before render() returns anything:



            if ($error instanceof IlluminateDatabaseEloquentModelNotFoundException) 
            $statusCode = 404;






            share|improve this answer












            Travis Britz and Guillaumehanotel each have half of your answer, but you're still missing a detail.



            From Travis Britz- Yes, include the tenant_id on the URI so it gets injected into the controller.
            From Guillaumehanotel- Also used the Eloquent findOrFail in that Id in your Controller (or whatever class the Controller is leveraging to do this, like a Repository or Service class).



            The last piece you're missing though is handling the error. You can do this in the Controller if you like, but I generally like making it a rule for my entire system that the IlluminateDatabaseEloquentModelNotFoundException Exceptions that come out of findOrFail() should always result in a 404.



            Go to app/Exceptions/Handler.php. I'm pretty sure Laravel auto-generates a meat and potatoes version of this file for you, but if you don't already have one, it should look something like this:



            <?php

            namespace AppExceptions;

            use IlluminateFoundationExceptionsHandler as ExceptionHandler;

            /**
            * Class Handler
            * @package AppExceptions
            */
            class Handler extends ExceptionHandler

            /**
            * Render an exception into an HTTP response.
            *
            * For our API, we need to override the call
            * to the parent.
            *
            * @param IlluminateHttpRequest $request
            * @param Exception $e
            * @return IlluminateHttpResponse
            */
            public function render($request, Exception $error)

            $exception = [
            'title' => 'Internal Error',
            'message' => $error->getMessage();
            ];
            $statusCode = 500;
            $headers = [
            'Content-Type', 'application/json'
            ];

            return response()->json($exception, $statusCode, $headers, JSON_PRETTY_PRINT);




            Laravel basically has a system-wide try/catch that sends all errors through here first. That's how errors get rendered into something the browser can actually interpret when you're in debug-mode, rather than just kill the process outright. This also gives you the opportunity to apply a few special rules.



            So all you need to do is tell Handler::render() to change the default error code that occurs when it sees the type of error that can only come from findOrFail(). (This kind of thing is why it's always good to make your own 'named exceptions', even if they do absolutely nothing except inherit the base Exception class.)



            Just add this just before render() returns anything:



            if ($error instanceof IlluminateDatabaseEloquentModelNotFoundException) 
            $statusCode = 404;







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 9 at 17:56









            Claymore

            885714




            885714











            • This is already the default behavior of Laravel. The reason for the 500 status code is an external library they're using (dingo/api) that has its own exception handling.
              – Travis Britz
              Nov 10 at 4:45

















            • This is already the default behavior of Laravel. The reason for the 500 status code is an external library they're using (dingo/api) that has its own exception handling.
              – Travis Britz
              Nov 10 at 4:45
















            This is already the default behavior of Laravel. The reason for the 500 status code is an external library they're using (dingo/api) that has its own exception handling.
            – Travis Britz
            Nov 10 at 4:45





            This is already the default behavior of Laravel. The reason for the 500 status code is an external library they're using (dingo/api) that has its own exception handling.
            – Travis Britz
            Nov 10 at 4:45


















            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53226948%2flaravel-validation-request-api-route-post-parameter%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

            Edmonton

            Crossroads (UK TV series)