2016-02-11 10 views
10

Sto costruendo un API REST con laravel 5.Come restituire gli errori AJAX da un controller Laravel?

In laravel 5, è possibile creare una sottoclasse App\Http\Requests\Request per definire le regole di convalida che devono essere soddisfatte prima di una particolare rotta verrà elaborato. Per esempio:

<?php 

namespace App\Http\Requests; 

use App\Http\Requests\Request; 

class BookStoreRequest extends Request { 

    public function authorize() { 
     return true; 
    } 

    public function rules() { 
     return [ 
      'title' => 'required', 
      'author_id' => 'required' 
     ]; 
    } 
} 

Se un client carica il percorso corrispondente tramite una richiesta AJAX, e BookStoreRequest ritiene che la richiesta non soddisfa le regole, verrà automagicamente restituirà l'errore (s) come un oggetto JSON. Per esempio:

{ 
    "title": [ 
    "The title field is required." 
    ] 
} 

Tuttavia, il metodo Request::rules() può convalidare solo l'ingresso, e anche se l'ingresso è valida, altri tipi di errori potrebbero sorgere dopo che la richiesta è già stata accettata e consegnato al controllore. Per esempio, diciamo che il controllore ha bisogno di scrivere le nuove informazioni libro in un file per qualche motivo, ma il file non può essere aperto:

<?php 

namespace App\Http\Controllers; 

use Illuminate\Http\Request; 

use App\Http\Requests; 
use App\Http\Controllers\Controller; 

use App\Http\Requests\BookCreateRequest; 

class BookController extends Controller { 

    public function store(BookStoreRequest $request) { 

     $file = fopen('/path/to/some/file.txt', 'a'); 

     // test to make sure we got a good file handle 
     if (false === $file) { 
      // HOW CAN I RETURN AN ERROR FROM HERE? 
     } 

     fwrite($file, 'book info goes here'); 
     fclose($file); 

     // inform the browser of success 
     return response()->json(true); 

    } 

} 

Ovviamente, ho potuto solo die(), ma questo è super-brutto. Preferirei restituire il mio messaggio di errore nello stesso formato degli errori di convalida. Come questo:

{ 
    "myErrorKey": [ 
    "A filesystem error occurred on the server. Please contact your administrator." 
    ] 
} 

ho potuto costruire il mio proprio oggetto JSON e restituire che, ma sicuramente laravel supporta in modo nativo.

Qual è il modo migliore/più pulito per farlo? O c'è un modo migliore per restituire errori di runtime (al contrario di validate time) da un'API Larst REST?

+0

Perché non si può semplicemente fare un 'return response() -> json (['error' => 'Your custom message']);'? –

+0

È possibile creare una classe di risposta JSON personalizzata – Digitlimit

+0

'return response() -> json()' lo restituirebbe con 200 OK. Voglio utilizzare un codice di risposta non 200 appropriato (ad es., 500 Internal Server Error). Sì, potrei anche scrivere a mano-ho appena dato per scontato che Laravel avesse già fornito un modo integrato e più strutturato per farlo. Forse è un'ipotesi errata. – greenie2600

risposta

13

È possibile impostare il codice di stato nella vostra risposta JSON, come di seguito:

return Response::json(['error' => 'Error msg'], 404); // Status code here 

O semplicemente utilizzando la funzione di supporto:

return response()->json(['error' => 'Error msg'], 404); // Status code here 
+0

usa la funzione response(), non $ response() –

3

lo si può fare in molti modi.

In primo luogo, è possibile utilizzare il semplice response()->json() fornendo un codice di stato:

return response()->json(/** response **/, 401); 

Oppure, in modo più Complexe per garantire che ogni errore è una risposta JSON, è possibile impostare un gestore di eccezioni per prendere un'eccezione speciale e restituire JSON.

Aprire App\Exceptions\Handler e procedere come segue:

class Handler extends ExceptionHandler 
{ 
    /** 
    * A list of the exception types that should not be reported. 
    * 
    * @var array 
    */ 
    protected $dontReport = [ 
     HttpException::class, 
     HttpResponseException::class, 
     ModelNotFoundException::class, 
     NotFoundHttpException::class, 
     // Don't report MyCustomException, it's only for returning son errors. 
     MyCustomException::class 
    ]; 

    public function render($request, Exception $e) 
    { 
     // This is a generic response. You can the check the logs for the exceptions 
     $code = 500; 
     $data = [ 
      "error" => "We couldn't hadle this request. Please contact support." 
     ]; 

     if($e instanceof MyCustomException) { 
      $code = $e->getStatusCode(); 
      $data = $e->getData(); 
     } 

     return response()->json($data, $code); 
    } 
} 

Ciò restituirà un JSON per qualsiasi eccezione generata nell'applicazione. Ora, creiamo MyCustomException, per esempio in app/Eccezioni:

class MyCustomException extends Exception { 

    protected $data; 
    protected $code; 

    public static function error($data, $code = 500) 
    { 
     $e = new self; 
     $e->setData($data); 
     $e->setStatusCode($code); 

     throw $e; 
    } 

    public function setStatusCode($code) 
    { 
     $this->code = $code; 
    } 

    public function setData($data) 
    { 
     $this->data = $data; 
    } 


    public function getStatusCode() 
    { 
     return $this->code; 
    } 

    public function getData() 
    { 
     return $this->data; 
    } 
} 

Ora possiamo semplicemente usare MyCustomException o qualsiasi eccezione si estende MyCustomException per restituire un errore di JSON.

public function store(BookStoreRequest $request) { 

    $file = fopen('/path/to/some/file.txt', 'a'); 

    // test to make sure we got a good file handle 
    if (false === $file) { 
     MyCustomException::error(['error' => 'could not open the file, check permissions.'], 403); 

    } 

    fwrite($file, 'book info goes here'); 
    fclose($file); 

    // inform the browser of success 
    return response()->json(true); 

} 

Ora, non solo eccezioni generate tramite MyCustomException restituirà un errore di JSON, ma qualsiasi altra eccezione generata in generale.

Problemi correlati